LeetCode 上共有 6 道有关买卖股票的系列问题:

本文就对这类问题的动态规划解法做一个总结。

设 dp[0][i] 为第 i 天持有股票时拥有的最大现金(不一定是第 i 天刚购入,也可能是第 i 天就购入股票并持有至第 i 天),设 dp[1][i] 为第 i 天未持有股票时拥有的最大现金,所得状态转移方程为:

代码实现如下:

不难写出如下代码。

由于最多完成 2 笔交易,我们可以把交易的过程划分为 5 种状态:

dp[0][i]:第 i 天不进行任何操作(可理解为从未购入股票的状态)时拥有的最大现金。

dp[1][i]:第 i 天恰好第一次买入股票,或第一次买入后一直持有股票时拥有的最大现金。

dp[2][i]:第 i 天处于第一次卖出股票,或第一次卖出股票后不持有股票时拥有的最大现金。

dp[3][i]:第 i 天恰好第二次买入股票,或第二次买入后一直持有股票时拥有的最大现金。

dp[4][i]:第 i 天处于第二次卖出股票,或第二次卖出股票后不持有股票时拥有的最大现金。

dp 数组初始化方面,dp[0][i] 的值显然都为 0,不进行任何操作肯定是没有现金的;dp[2][0] 与 dp[4][0] 应为 0,因为第 0 天什么都不做肯定持有最大的现金 0,若第 0 天买入则持有的现金肯定变成了负数;dp[1][0] 根据前面 I 和 II 的讨论也应初始化为 -prices[i];dp[3][0],笔者一开始也初始化为 0,想着第一次还没有交易怎么能谈第二次买入呢?实际上是不对的,可以看作第 0 天第一次买入并卖出,然后再买入一次(第二次买入),故初始化为 -prices[i]。

实现代码如下:

和 III 类似,只不过变成了最多交易 k 次。从 III 的递推公式我们可知,奇数行和偶数行的状态转移方程是有规律的,即:

加入了冷冻期后,买卖股票的状态就能划分为如下四种:

dp[1][i]:第 i 天未持有股票、且当天已经度过冷冻期时拥有的最大现金。

dp[3][i]:第 i 天未持有股票、且当天恰好为冷冻期时拥有的最大现金。

这个就比较简单了,在 #122 买卖股票的**时机 II 的基础上,卖股票的时候多减手续费就行。