Say you have an array for which the ith element is the price of a given stock on day i.數組
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions:spa
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).rest
After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)code
Example:ip
prices = [1, 2, 3, 0, 2] maxProfit = 3 transactions = [buy, sell, cooldown, buy, sell]
由於當前日期買賣股票會受到以前日期買賣股票行爲的影響,首先考慮到用DP解決。element
這道題比較麻煩的是有個cooldown的限制,其實本質也就是買與賣之間的限制。對於某一天,股票有三種狀態: buy, sell, cooldown, sell與cooldown咱們能夠合併成一種狀態,由於手裏最終都沒股票,最終須要的結果是sell,即手裏股票賣了得到最大利潤。因此咱們能夠用兩個DP數組分別記錄當前持股跟未持股的狀態。而後根據題目中的限制條件,理清兩個DP數組的表達式。it
對於當天最終未持股的狀態,最終最大利潤有兩種可能,一是今天沒動做跟昨天未持股狀態同樣,二是昨天持股了,今天賣了。因此咱們只要取這二者之間最大值便可,表達式以下:io
sellDp[i] = Math.max(sellDp[i - 1], buyDp[i - 1] + prices[i]);
對於當天最終持股的狀態,最終最大利潤有兩種可能,一是今天沒動做跟昨天持股狀態同樣,二是前天還沒持股,今天買了股票,這裏是由於cooldown的緣由,因此今天買股要追溯到前天的狀態。咱們只要取這二者之間最大值便可,表達式以下:class
buyDp[i] = Math.max(buyDp[i - 1], sellDp[i - 2] - prices[i]);
最終咱們要求的結果是im
sellDp[n - 1] 表示最後一天結束時手裏沒股票時的累積最大利潤
固然,這裏空間複雜度是能夠降到O(1)的,具體見第二種代碼實現。
time: O(n), space: O(n)
public class Solution { public int maxProfit(int[] prices) { if (prices == null || prices.length == 0) { return 0; } // 表示當天最終未持股的狀況下,當天結束後的累計最大利潤 int[] sellDp = new int[prices.length]; // 表示當天最終持股的狀況下,當天結束後的累計最大利潤 int[] buyDp = new int[prices.length]; // 考慮初始狀況 buyDp[0] = -prices[0]; sellDp[0] = 0; for (int i = 1; i < prices.length; i++) { sellDp[i] = Math.max(sellDp[i - 1], buyDp[i - 1] + prices[i]); if (i >= 2) { buyDp[i] = Math.max(buyDp[i - 1], sellDp[i - 2] - prices[i]); } else { buyDp[i] = Math.max(buyDp[i - 1], -prices[i]); } } return sellDp[prices.length - 1]; } }
public class Solution { public int maxProfit(int[] prices) { if (prices == null || prices.length == 0) { return 0; } int currBuy = -prices[0]; int currSell = 0; int prevSell = 0; for (int i = 1; i < prices.length; i++) { int temp = currSell; currSell = Math.max(currSell, currBuy + prices[i]); if (i >= 2) { currBuy = Math.max(currBuy, prevSell - prices[i]); } else { currBuy = Math.max(currBuy, -prices[i]); } prevSell = temp; } return currSell; } }