第 1 步:状态定义
- 状态定义:
dp[i][j]
表示在[0, i]
区间里(这个状态依然是前缀性质的),状态为j
的最大收益。
说明:j
的含义如下。
1、j = 0
:还未开始交易;
2、j = 1
:第 1 次买入一支股票;
3、j = 2
:第 1 次卖出一支股票;
4、j = 3
:第 2 次买入一支股票;
5、j = 4
:第 2 次卖出一支股票。
第 2 步:状态转移方程
“状态转移方程”可以用下面的图表示,它的特点是:状态要么停留,要么向后面走,状态不能回退。
具体表示式请见代码注释。
第 3 步: 思考初始化
第 0 天的时候只能初始化两个状态,而状态 3
(表示第 2 次持股)只能赋值为一个不可能的数。
注意:只有在之前的状态有被赋值的时候,才可能有当前状态。
第 4 步: 思考输出
最后一天不持股的状态都可能成为候选的最大利润。
Java 代码:
public class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
if (len < 2) {
return 0;
}
// dp[i][j] ,表示 [0, i] 区间里,状态为 j 的最大收益
// j = 0:什么都不操作
// j = 1:第 1 次买入一支股票
// j = 2:第 1 次卖出一支股票
// j = 3:第 2 次买入一支股票
// j = 4:第 2 次卖出一支股票
// 初始化
int[][] dp = new int[len][5];
dp[0][0] = 0;
dp[0][1] = -prices[0];
// 3 状态都还没有发生,因此应该赋值为一个不可能的数
for (int i = 0; i < len; i++) {
dp[i][3] = Integer.MIN_VALUE;
}
// 状态转移只有 2 种情况:
// 情况 1:什么都不做
// 情况 2:由上一个状态转移过来
for (int i = 1; i < len; i++) {
// j = 0 的值永远是 0
dp[i][0] = 0;
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1] + prices[i]);
dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]);
}
// 最大值只发生在不持股的时候,因此来源有 3 个:j = 0 ,j = 2, j = 4
return Math.max(0, Math.max(dp[len - 1][2], dp[len - 1][4]));
}
}
第 5 步: 思考状态压缩
因为今天的值只参考了昨天的值(并且是其它状态昨天的值),或者使用滚动数组,或者直接去掉第 1 维。
Java 代码:
public class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
if (len < 2) {
return 0;
}
// dp[i][j] ,表示 [0, i] 区间里,状态为 j 的最大收益
// j = 0:什么都不操作
// j = 1:第 1 次买入一支股票
// j = 2:第 1 次卖出一支股票
// j = 3:第 2 次买入一支股票
// j = 4:第 2 次卖出一支股票
int[] dp = new int[5];
dp[1] = -prices[0];
// 3 状态都还没有发生,因此应该赋值为一个不可能的数
dp[3] = Integer.MIN_VALUE;
for (int i = 1; i < len; i++) {
dp[0] = 0;
dp[1] = Math.max(dp[1], dp[0] - prices[i]);
dp[2] = Math.max(dp[2], dp[1] + prices[i]);
dp[3] = Math.max(dp[3], dp[2] - prices[i]);
dp[4] = Math.max(dp[4], dp[3] + prices[i]);
}
return Math.max(0, Math.max(dp[2], dp[4]));
}
}
- 差分思想没有说。
- 两次交易不能有重合,因此可以转化为两个第 121 题:枚举分割点,分别进行一笔交易赚的最大利润,即为这种情况下的最大利润。