LeetCode-309. 最佳买卖股票时机含冷冻期
题目来源
题目详情
给定一个整数数组,其中第_ i_ 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例:
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
题解分析
解法一:动态规划
- 本题是买卖股票问题的变种,其他相关的问题还有:
- 这题买卖股票的解法可以使用动态规划的思想来做,首先考虑到有买入卖出以及冻结期,看似是一个十分复杂的问题,确实它的动态状态转换也有一定难度。
- 根据题意,可以将某一个时刻的状态划分为三种:持股,空股且处于冻结期,空股但处于非冻结期。分别使用dp[i][0],dp[i][1],dp[i][2]来表示。
- 对于dp[i][0],这个状态可以由max(dp[i-1][0], dp[i-1][2] - prices[i])转换而来。这里可以进行的操作是,要么继续持股,要么在第i天买入一直股票,这要求前一天处于空股且非冻结状态。
- 对于dp[i][1],它的状态可以直接由dp[i-1][0] + prices[i]状态转换而来,这个状态只能由第i天卖出一支股票来转移。
- 对于dp[i][2],它的状态转移方程为:max(dp[i-1][1], dp[i-1][2]),即从空股状态转换而来,因为要求这次处于非冻结状态,所以这一天不可以买卖股票。
class Solution {
public int maxProfit(int[] prices) {
int n = prices.length;
int[][]dp = new int[n][3];
dp[0][0] = -prices[0];
dp[0][1] = 0;
dp[0][2] = 0;
for(int i=1; i<n; i++){
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][2] - prices[i]);// 仍然持股,或者在第i天(非冻结期)买入一支股票
dp[i][1] = dp[i-1][0] + prices[i]; // 第i天后没有持股,而且处于冻结期,说明第i天卖出了股票
dp[i][2] = Math.max(dp[i-1][1], dp[i-1][2]); // 第i天没有持股,而且处于非冻结期,说明当前没有买入卖出的操作,直接继承之前的状态
}
return Math.max(dp[n-1][1], dp[n-1][2]);
}
}
解法二:动态规划压缩数组
- 看到动态数组的题目都应该下意识的想到压缩数组这种优化方法。
- 因为第i天的状态只能依赖于第i-1天,所以这里完全可以使用一维数组。进一步地,考虑到第二维长度最大为3,所以本题连数组都不需要,直接设置几个变量表示三类状态即可。
class Solution {
public int maxProfit(int[] prices) {
int n = prices.length;
int pre0 = -prices[0];
int pre1 = 0;
int pre2 = 0;
for(int i=1; i<n; i++){
int temp0 = pre0, temp1 = pre1, temp2 = pre2;
pre0 = Math.max(temp0, temp2 - prices[i]);// 仍然持股,或者在第i天(非冻结期)买入一支股票
pre1 = temp0 + prices[i]; // 第i天后没有持股,而且处于冻结期,说明第i天卖出了股票
pre2 = Math.max(temp1, temp2); // 第i天没有持股,而且处于非冻结期,说明当前没有买入卖出的操作,直接继承之前的状态
}
return Math.max(pre1, pre2);
}
}
Either Excellent or Rusty
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了