手撕代码:leetcode 309最佳买卖股票时机含冷冻期
转载于:https://segmentfault.com/a/1190000014746613
给定一个整数数组,其中第i个元素代表了第i天的股票价格。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
*你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
*卖出股票后,你无法在第二天买入股票(即冷冻期为1天)
示例:
输入: [1,2,3,0,2] 输出: 3 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
思路和代码
这里转述leetcode上一个非常漂亮的解答。
在第i天时,我们可以进行三种操作,抛出或是买入或是啥都不干。但是具体下来,又有四种情况:
1.在持有一只股票的时候抛出
2.在持有一只股票的时候啥都不干
3.在持有0只股票的时候啥都不干
4.在持有0只股票的时候买入
而这些操作之间又存在潜在的联系,也就是说我如果在第i天进行以上四种操作之一,那么意味着我在第i-1天一定进行了四种操作中的某一种,从而支持我第i天的操作。具体关联如下:
1.第i天之行的操作:在持有一只股票的时候抛出=>在第i-1天执行的操作:在持有一只股票的时候啥都不干/在持有0只股票的时候买入
2.第i天执行的操作:在持有一只股票的时候啥也不干=>在第i-1天执行的操作:在持有一只股票的时候啥也不干/在持有0只股票的会后买入
3.第i天执行的操作:在持有0只股票的时候买入=>在第i-1天执行的操作:在持有0只股票的时候啥也不做
4.第i天执行的操作:在持有0只股票的时候啥也不做=>在第i-1天执行的操作:在持有0只股票的时候啥也不做/在持有一只股票的时候抛出
我们采用动态规划的思想,分别记录第i-1天的时候这四种情况的最大收入,并由此比较并得出第i天时这四种情况的最大收入。最后比较最后一天这四种情况可以得到的最大收益,代码如下:
1 int maxProfix(int prices[],int size) 2 { 3 if(size==0)return 0; 4 int hasOneDoNothing=-prices[0]; 5 int hasOneSellIt=0; 6 int hasZeroDoNothing=0; 7 int hasZeroBuyOne=-prices[0]; 8 for (int i = 0; i <size ; ++i) { 9 int tmp1=hasOneDoNothing; 10 int tmp2=hasOneSellIt; 11 int tmp3=hasZeroDoNothing; 12 int tmp4=hasZeroBuyOne; 13 hasOneDoNothing=tmp1>tmp4?tmp1:tmp4; 14 hasOneSellIt=(tmp1>tmp4?tmp1:tmp4)+prices[i]; 15 hasZeroDoNothing=tmp2>tmp3?tmp2:tmp3; 16 hasZeroBuyOne=tmp3-prices[i]; 17 } 18 return hasZeroDoNothing>hasOneSellIt?hasZeroDoNothing:hasOneSellIt; 19 }
这里你可能会困惑,为什么只比较 在最后一天持有0只股票并且不进行任何操作 和 在最后一天持有股票并抛出这两种情况呢?
假设我们最后一天持有股票并且不抛出,那么意味着在之前买入最后一只股票的那一天,如果我们不购入将会得到更大的收益。因此抛出一定比不抛出得到的损失小。
至于另一种情况,即最后一天又买入了股票,显然它一定比不买入股票得到的收益少啊。
因此我们只要比较最初提出的两种情况即可。