309. 最佳买卖股票时机含冷冻期
时间:2020年7月10日
知识点:动态规划
题目链接: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/
题目
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例
输入:
[1,2,3,0,2]
输出:3
解释:对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]。
解法
- 我们用dp[i]表示第i天结束之后的累计的最大收益
- 第i天结束后有三种情况
状态一:手上有股票,记为dp[i][0]
状态二:手上没有股票,还处于冷冻期,记为dp[i][1]
状态三:手上没有股票,不处于冷冻期,还没有买股票(称为观望期),记为dp[i][2] - 状态转移
- 什么情况下能变成状态一?
- 原来就持有股票,即dp[i-1][0]
- 在第i天买入,什么情况下能买入?手上股票卖出了且过了冷冻期,即dp[i-1][2],买股票累计的最大收益就减少,减少的值是现在股票的价格
- dp[i][0] = max(dp[i-1][0],dp[i-1][2]-price[i])
- 什么情况下能变成状态二?
- 在昨天卖出了股票,昨天手上要有股票即dp[i-1][0],卖出股票收益增加,增加的值是现在股票的价格
- dp[i][1]=dp[i-1][0]+price[i]
- 什么情况下能变成状态三?
- 前天卖出股票,昨天手上没股票,且在冷冻期,今天解封可以买股票,即dp[i-1][1]
- 昨天手上没股票且没在冷冻期,处于等等期,即dp[i-1][2]
- dp[i][2]=max(dp[i-1][1],dp[i-1][2])
- 什么情况下能变成状态一?
- 总共有n天的话,结果是max(dp[n-1][0],dp[n-1][1],dp[n-1][2]),但是在最后一天手上有股票也不能换钱,其实就是求max(dp[n-1][1],dp[n-1][2])
- 注意dp数组的边界
dp[0][0] = -price[0] 若在第0天拥有股票,则就是在第0天买入,累积的收益为负数
dp[0][1] = 0 第0天不存在冷冻期
dp[0][2] = 0 在第0天没买股票,累积收益为0
代码
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty())
return 0;
int num = prices.size();
// dp[i][0]: 手上有股票时的累积最大收益
// dp[i][1]: 手上没有股票,并且处于冷冻期中的累计最大收益
// dp[i][2]: 手上没有股票,并且不在冷冻期中的累计最大收益
vector<vector<int>> dp(num, vector<int>(3));
dp[0][0] = -prices[0];
for (int i = 1; i < num; i++) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i]);
dp[i][1] = dp[i - 1][0] + prices[i];
dp[i][2] = max(dp[i - 1][1], dp[i - 1][2]);
}
return max(dp[num - 1][1], dp[num - 1][2]);
}
};
int main()
{
vector<int> v(10);
v[0]=1;v[1]=2;v[2]=3;v[3]=0;v[4]=2;
Solution s;
cout<<s.maxProfit(v);
return 0;
}
优化空间,注意到上面的状态转移方程中,dp[i][X]只与 dp[i-1][X] 有关,而与dp[i-2][X]及之前的所有状态都无关,因此我们不必存储这些无关的状态
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty())
return 0;
int num = prices.size();
// dp0: 手上有股票时的累积最大收益
// dp1: 手上没有股票,并且处于冷冻期中的累计最大收益
// dp2: 手上没有股票,并且不在冷冻期中的累计最大收益
int dp0 = -prices[0];
int dp1 = 0;
int dp2 = 0;
for (int i = 1; i < num; i++) {
int tmp0 = max(dp0, dp2 - prices[i]);
int tmp1 = dp0 + prices[i];
int tmp2 = max(dp1, dp2);
dp0 = tmp0;
dp1 = tmp1;
dp2 = tmp2;
}
return max(dp1, dp2);
}
};
int main()
{
vector<int> v(10);
v[0]=1;v[1]=2;v[2]=3;v[3]=0;v[4]=2;
Solution s;
cout<<s.maxProfit(v);
return 0;
}
今天也是爱zz的一天哦!
本文探讨了在股票交易中包含冷冻期的最优买卖策略,通过动态规划算法解决最大利润问题,介绍了状态转移过程和代码实现,同时提供了空间优化方案。

381

被折叠的 条评论
为什么被折叠?



