问题:给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为
1 天)。
思路:
-
首先定义状态,dp[i][0] 表示第i天未持有股票的最高收益,dp[i][1] 表示第i天持有股票的最高收益。那么我们所求结果为dp[n][0] 最后一天未持有股票的最高收益,n 表示最后一天。 -
确定状态转移方程。
- 第i天未持有股票有两种情况:1.昨天没买 2.昨天买了,今天卖了,所以有
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]); - 第i天持有股票的情况需要注意,也分为两种情况
- 前天卖了股票,昨天是冷冻期。
- 这种情况包含了冷冻期这一特殊条件,因为
dp[i-1][0] 表示第i-1 天未持有股票时的最高收益,所以有可能是第i-1 天刚卖了股票,也有可能是第i-2 天刚卖了股票,第i-1 天是冷冻期。因此若第i-1 天为冷冻期,则第i 天的收益应该为dp[i-2][0] - prices[i] - 昨天就持有股票
- 所以有
dp[i][1] = Math.max(dp[i-1][0] - prices[i], dp[i-1][1])
- 初始条件(base case)
- 第一天时,有
- 第一天没持有股票,利润为
0 。有:dp[0][0] = 0 - 一天持有股票,说明第一天买了股票,利润为
-prices[0] 。有dp[0][1] = -prices[0] 。 - 因为上面列出的状态转移方程中
dp[i][1] 的状态和第i-1天以及第i-2天都有关系。所以第二天的情况也需要提前考虑
- 第二天未持有股票,和状态转移方程一致,两种情况:1.第一天也就是昨天没买 2.昨天买了,今天卖了
- 第二天持有股票,这里需要注意。因为是第二天,所以不存在冷冻期,两种情况:1.今天买了,2.昨天买了,今天没卖。所以有
dp[1][1] = Math.max(dp[0][0] - prices[0], dp[0][1])
接下来就是根据base case和状态转移方程写代码了。
class Solution {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length + 1][2];
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i = 1; i < prices.length; i++){
if(i-2 == -1){
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
dp[i][1] = Math.max(dp[i-1][0] - prices[i], dp[i-1][1]);
continue;
}
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
dp[i][1] = Math.max(dp[i-2][0] - prices[i], dp[i-1][1]);
}
return dp[prices.length - 1][0] < 0 ? 0 : dp[prices.length - 1][0];
}
}
刷题小白参考题解总结的思路,若哪里有误,望指正。欢迎讨论。
|