题目要求
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:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)
Example:
prices = [1, 2, 3, 0, 2]
maxProfit = 3
transactions = [buy, sell, cooldown, buy, sell]
和前面几题相比,这题还增加了一个限制条件,也就是说我们在抛出股票之后,还需要冷却一天才可以买入下一只股票。那么我们进行什么样的操作才能使收益最大呢?
思路和代码
这里转述leetcode上一个非常漂亮的解答。
在第i天时,我们可以进行两种操作,抛出或是买入或是啥都不干。但是具体下来,又有四种情况:
- 在持有一只股票的时候抛出
- 在持有一只股票的时候啥都不干
- 在持有0只股票的时候啥都不干
- 在持有0只股票的时候买入
而在这些操作之间又存在潜在的联系,也就是说我如果在第i天进行以上四种操作之一,那么意味着我在第i-1天一定进行了这四种操作中的某一种,从而支持我第i天的操作。具体关联如下:
- 第i天执行的操作:在持有一只股票的时候抛出 => 在第i-1天执行的操作: 在持有一只股票的时候啥都不干/在持有0只股票的时候买入
- 第i天执行的操作:在持有一只股票的时候啥也不干 => 在第i-1天执行的操作:在持有一只股票的时候啥也不干/在持有0只股票的会后买入
- 第i天执行的操作:在持有0只股票的时候买入 => 在第i-1天执行的操作:在持有0只股票的时候啥也不做
- 第i天执行的操作:在持有0只股票的时候啥也不做 => 在第i-1天执行的操作:在持有0只股票的时候啥也不做/在持有一只股票的时候抛出
我们采用动态规划的思想,分别记录第i-1天的时候这四种情况的最大收入,并由此比较并得出第i天时这四种情况的最大收入。最后比较最后一天这四种情况可以得到的最大收益,代码如下:
public int maxProfit(int[] prices) {
if(prices.length == 0) return 0;
int hasOneDoNothing = -prices[0];
int hasOneSellIt = 0;
int hasZeroDoNothing = 0;
int hasZeroBuyOne = -prices[0];
for(int i = 1 ; i<prices.length ; i++){
int tmp1 = hasOneDoNothing;
int tmp2 = hasOneSellIt;
int tmp3 = hasZeroDoNothing;
int tmp4 = hasZeroBuyOne;
hasOneDoNothing = tmp1 > tmp4 ? tmp1 : tmp4;
hasOneSellIt = (tmp1 > tmp4 ? tmp1 : tmp4) + prices[i];
hasZeroDoNothing = tmp2 > tmp3 ? tmp2 : tmp3;
hasZeroBuyOne = tmp3 - prices[i];
}
return hasZeroDoNothing > hasOneSellIt ? hasZeroDoNothing : hasOneSellIt;
}
这里你可能会困惑,为什么只比较 在最后一天持有0只股票并且不进行任何操作 和 在最后一天持有股票并抛出这两种情况呢?
假设我们最后一天持有股票并且不抛出,那么意味着在之前买入最后一只股票的那一天,如果我们不购入将会得到更大的收益。因此抛出一定比不抛出得到的损失小。
至于另一种情况,即最后一天又买入了股票,显然它一定比不买入股票得到的收益少啊。
因此我们只要比较最初提出的两种情况即可。
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。