309. 最佳买卖股票时机含冷冻期
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例:
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
来源:力扣(LeetCode)
参考链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown
思路
由于后面的利润是基于前面的操作的,比如,你今天卖了,明天就是冷冻期,不能进行操作。或者,今天买了,明天才能卖或者什么都不操作,但肯定不能再买了。所以这是一个状态转移的过程,要使用动态规划解决。考虑买入利润为负,卖出利润为正,第i
天的利润为f[i]
。
根据是否拥有股票和是否处于冷冻期可以将一天结束的状态分为三种情况,本来是2×2种,但是,买入股票即拥有股票,必不存在冷冻期。而没有股票可能是因为卖出进入冷冻期,前一天是没股票,今天也没买入就不进入冷冻期。
第一种
- 持有一支股票,当天利润为
f[i][0]
;
第二种
- 没有持有股票,在冷冻期,当天利润为
f[i][1]
;
第三种
- 没有持有股票,没在冷冻期,当天利润为
f[i][2]
;
如果处于第一种情况,可能是前一天拥有股票,今天没有操作。或者,前一天没有股票,而且没进入冷冻期,今天买入,所以状态转移方程为
f[i][0] = max(f[i-1][0],f[i-1][2]-prices[i]);
如果处于第二种情况,那就是今天卖出了,前一天的必须有一支股票,状态转移方程为
f[i][1] = f[i-1][0] + prices[i];
如果处于第三种情况,那可能是前一天处于冷冻期,或者前一天也处于第三种情况。状态转移方程为
f[i][2] = max(f[i-1][1],f[i-1][2]);
最后,最大利润就是三种情况中的最大值,但是最后一天还拥有一支股票,显然不会是最大值,所以最后结果为
max(f[i][1],f[i][2]);
仔细一看,由于前一天的状态使用过之后,就没有保存的必要,所以可以使用迭代更新的方法节省空间。代码如下:
代码
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if (n == 0)
return 0;
int f0 = -prices[0];
int f1 = 0;
int f2 = 0;
for (int i = 1;i < n;i++){
int new0 = max(f0,f2-prices[i]);
int new1 = f0 + prices[i];
int new2 = max(f1,f2);
f0 = new0;
f1 = new1;
f2 = new2;
}
return max(f1,f2);
}
};