买卖股票的最佳时机问题

股票问题

力扣上的股票问题可以总结为以下几类:

对于这些问题,可以统一用动态规划来解决,思路如下:
首先,知道每一天可以有几种状态:持有 k 张股票;不持有股票; 处于冷冻期等。

  1. 确定 dp数组及下标的含义:dp[j][k] 表示第 j 天可剩余的最多现金,k为当天所处的状态
  2. 确定递推公式:dp[j][k]应该如何由之前的状态表示。
  3. dp 数组如何初始化:一般初始化第一天,即dp[0][k]
  4. 确定遍历顺序:由于后一天的结果由前一天得出,因此从前往后遍历
  5. 举例推导dp数组

力扣第188题 题目描述如下:
给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

首先每一天有 k * 2 种状态: // 本题可以使用滚动数组 dp[k*2]来表示每一天状态
k 偶数 --- 持有第 k 张股票;
k+1 奇数 --- 卖出第 k 张股票;

1. 确定 dp 数组
vector<vector<int>> dp(prices.size(), vector<int>(k * 2, 0));
2. 确定递推公式 k为偶数
// 当天持有第 k 张股票:可能是前一天就持有股票;或当天买入一只股票,则前一天不持有股票 -> 取最大值
dp[i][k] = max(dp[i-1][k], dp[i-1][k]-prices[i]);
// 当天卖出第 k 张股票:前一天就卖出股票;或当天卖出一只股票,则前一天处于持有第 k 张股票状态
dp[i][k+1] = max(dp[i-1][k+1], dp[i-1][k]+prices[i]);
3. 初始化:第0天的状态的值
for (int j=0; j<k*2; j+=2) {
	dp[0][j] = -prices[0]; //当天买入一只股票,花费了 prices[0]
	dp[0][j+1] = 0;  // 可以看成当天买入又卖出,或者没有操作
}
4. 确定遍历顺序: 从前往后遍历
for (int i=1; i<prices.size(); ++i) {
	for (int j=0; j<2*k; j+=2) {
		dp[i][j] = max(dp[i-1][j], dp[i-1][j+1]-prices[i]);
		dp[i][j+1] = max(dp[i-1][j+1], dp[i-1][j]+prices[i]);
	}
}

力扣第309题 题目描述如下:
给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

首先每一天有三种状态:
0 --- 持有一张股票;
1 --- 不持有股票;
2 --- 处于冷冻期(包含两种情况,1.前一天卖出股票,2.更早卖出股票。但可以统一记为冷冻期,因为既没有股票在手上,当天也没有任何操作)

1. 确定 dp 数组
vector<vector<int>> dp(prices.size(), vector<int>(3, 0));
2. 确定递推公式
// 当天持有一只股票:可能是前一天就持有股票;或当天买入一只股票,这种情况前一天必须为冷冻期 -> 取最大值
dp[j][0] = max(dp[j-1][0], dp[j-1][2]-prices[j]);
// 当天不持有股票:前一天就不持有股票;或当天卖出一只股票,则前一天处于持有股票状态
dp[j][1] = max(dp[j-1][1], dp[j-1][0]+prices[j]);
// 处于冷冻期:前一天就处于冷冻期;或前一天卖出一张股票
dp[j][2] = max(dp[j-1][2], dp[j-1][1]);
3. 初始化:第0天的三种状态的值
dp[0][0] = -prices[0]; //当天买入一只股票,花费了 prices[0]
dp[0][1] = 0;  // 可以看成当天买入又卖出,或者没有操作
dp[0][2] = 0;  // 冷冻期,相当于没有操作
4. 确定遍历顺序: 从前往后遍历
for (int j=1; j<prices.size(); ++j){
	dp[j][0] = max(dp[j-1][0], dp[j-1][2]-prices[j]);
	dp[j][1] = max(dp[j-1][1], dp[j-1][0]+prices[j]);
	dp[j][2] = max(dp[j-1][2], dp[j-1][1]);
}

参考:
代码随想录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值