From 1c1b244d972f2d32f3bc7162886cd93653e469e4 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Wed, 23 Dec 2020 17:19:53 +0100 Subject: [PATCH] Add dynamic programming version. --- .../dpBestTimeToBuySellStocks.test.js | 48 +++++++++++++++++++ .../dpBestTimeToBuySellStocks.js | 25 ++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/algorithms/uncategorized/best-time-to-buy-sell-stocks/__tests__/dpBestTimeToBuySellStocks.test.js create mode 100644 src/algorithms/uncategorized/best-time-to-buy-sell-stocks/dpBestTimeToBuySellStocks.js diff --git a/src/algorithms/uncategorized/best-time-to-buy-sell-stocks/__tests__/dpBestTimeToBuySellStocks.test.js b/src/algorithms/uncategorized/best-time-to-buy-sell-stocks/__tests__/dpBestTimeToBuySellStocks.test.js new file mode 100644 index 0000000000..5904ee54f0 --- /dev/null +++ b/src/algorithms/uncategorized/best-time-to-buy-sell-stocks/__tests__/dpBestTimeToBuySellStocks.test.js @@ -0,0 +1,48 @@ +import dpBestTimeToBuySellStocks from '../dpBestTimeToBuySellStocks'; + +describe('dpBestTimeToBuySellStocks', () => { + it('should find the best time to buy and sell stocks', () => { + let visit; + + expect(dpBestTimeToBuySellStocks([1, 5])).toEqual(4); + + visit = jest.fn(); + expect(dpBestTimeToBuySellStocks([1], visit)).toEqual(0); + expect(visit).toHaveBeenCalledTimes(1); + + visit = jest.fn(); + expect(dpBestTimeToBuySellStocks([1, 5], visit)).toEqual(4); + expect(visit).toHaveBeenCalledTimes(2); + + visit = jest.fn(); + expect(dpBestTimeToBuySellStocks([5, 1], visit)).toEqual(0); + expect(visit).toHaveBeenCalledTimes(2); + + visit = jest.fn(); + expect(dpBestTimeToBuySellStocks([1, 5, 10], visit)).toEqual(9); + expect(visit).toHaveBeenCalledTimes(3); + + visit = jest.fn(); + expect(dpBestTimeToBuySellStocks([10, 1, 5, 20, 15, 21], visit)).toEqual(25); + expect(visit).toHaveBeenCalledTimes(6); + + visit = jest.fn(); + expect(dpBestTimeToBuySellStocks([7, 1, 5, 3, 6, 4], visit)).toEqual(7); + expect(visit).toHaveBeenCalledTimes(6); + + visit = jest.fn(); + expect(dpBestTimeToBuySellStocks([1, 2, 3, 4, 5], visit)).toEqual(4); + expect(visit).toHaveBeenCalledTimes(5); + + visit = jest.fn(); + expect(dpBestTimeToBuySellStocks([7, 6, 4, 3, 1], visit)).toEqual(0); + expect(visit).toHaveBeenCalledTimes(5); + + visit = jest.fn(); + expect(dpBestTimeToBuySellStocks( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + visit, + )).toEqual(19); + expect(visit).toHaveBeenCalledTimes(20); + }); +}); diff --git a/src/algorithms/uncategorized/best-time-to-buy-sell-stocks/dpBestTimeToBuySellStocks.js b/src/algorithms/uncategorized/best-time-to-buy-sell-stocks/dpBestTimeToBuySellStocks.js new file mode 100644 index 0000000000..8bf1645f11 --- /dev/null +++ b/src/algorithms/uncategorized/best-time-to-buy-sell-stocks/dpBestTimeToBuySellStocks.js @@ -0,0 +1,25 @@ +/** + * Finds the maximum profit from selling and buying the stocks. + * DYNAMIC PROGRAMMING APPROACH. + * + * @param {number[]} prices - Array of stock prices, i.e. [7, 6, 4, 3, 1] + * @param {function(): void} visit - Visiting callback to calculate the number of iterations. + * @return {number} - The maximum profit + */ +const dpBestTimeToBuySellStocks = (prices, visit = () => {}) => { + visit(); + let lastBuy = -prices[0]; + let lastSold = 0; + + for (let day = 1; day < prices.length; day += 1) { + visit(); + const curBuy = Math.max(lastBuy, lastSold - prices[day]); + const curSold = Math.max(lastSold, lastBuy + prices[day]); + lastBuy = curBuy; + lastSold = curSold; + } + + return lastSold; +}; + +export default dpBestTimeToBuySellStocks;