1. 题目
读题
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/submissions/429217002/
考查点
2. 解法
思路
思路是这样的:
首先,我们需要定义三个状态,分别表示第 i 天持有股票、不持有股票且处于冷冻期、不持有股票且不处于冷冻期的最大利润。我们用一个二维数组 dp 来存储这些状态,其中 dp[i][j] 表示第 i 天处于第 j 种状态的最大利润,j 可以是 0、1 或 2。
然后,我们需要考虑每个状态之间的转移关系。对于第 i 天持有股票的状态,它可能是由第 i - 1 天就持有股票的状态转移而来,也可能是由第 i - 1 天不持有股票且不处于冷冻期的状态转移而来,即在第 i 天买入股票。因此,我们需要在这两种情况中取最大值,同时减去第 i 天的股票价格。
对于第 i 天不持有股票且处于冷冻期的状态,它只能是由第 i - 1 天持有股票的状态转移而来,即在第 i - 1 天卖出股票。因此,我们只需要加上第 i 天的股票价格。
对于第 i 天不持有股票且不处于冷冻期的状态,它可能是由第 i - 1 天就不持有股票且不处于冷冻期的状态转移而来,也可能是由第 i - 1 天不持有股票且处于冷冻期的状态转移而来,即在第 i - 1 天结束了冷冻期。因此,我们需要在这两种情况中取最大值。
最后,我们需要考虑初始状态。对于第 0 天,我们可以假设只有三种可能:买入股票、不买入股票且处于冷冻期、不买入股票且不处于冷冻期。显然,前两种情况都是不合理的,因为我们不能在没有股票的情况下卖出股票或进入冷冻期。因此,我们只需要将第 0 天持有股票的利润设为负数,即减去第 0 天的股票价格,而将其他两种状态的利润设为零。
根据上述分析,我们可以得到如下的状态转移方程:
dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i])
dp[i][1] = dp[i - 1][0] + prices[i]
dp[i][2] = max(dp[i - 1][2], dp[i - 1][1])
最终的答案就是最后一天不持有股票的利润中的较大值,即 max(dp[n - 1][1], dp[n - 1][2])。
代码逻辑
代码的逻辑可以分为以下几个步骤:
- 定义一个二维数组 dp,用来存储每一天的三种状态的最大利润。
- 初始化第 0 天的状态,即 dp[0][0] = -prices[0], dp[0][1] = 0, dp[0][2] = 0。
- 遍历从第 1 天到第 n - 1 天的股票价格,根据状态转移方程更新 dp 数组的值。
- 返回最后一天不持有股票的利润中的较大值,即 max(dp[n - 1][1], dp[n - 1][2])。
具体实现
class Solution { public int maxProfit(int[] prices) { // 定义一个二维数组 dp,用来存储每一天的三种状态的最大利润 int n = prices.length; int[][] dp = new int[n][3]; // 初始化第 0 天的状态 dp[0][0] = -prices[0]; // 第 0 天买入股票 dp[0][1] = 0; // 第 0 天不可能处于冷冻期 dp[0][2] = 0; // 第 0 天不可能卖出股票 // 遍历从第 1 天到第 n - 1 天的股票价格 for (int i = 1; i < n; i++) { // 更新第 i 天持有股票的最大利润,取前一天持有股票或者前一天不持有股票且不处于冷冻期并在第 i 天买入股票的较大值 dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][2] - prices[i]); // 更新第 i 天不持有股票且处于冷冻期的最大利润,等于前一天持有股票并在第 i 天卖出股票 dp[i][1] = dp[i - 1][0] + prices[i]; // 更新第 i 天不持有股票且不处于冷冻期的最大利润,取前一天不持有股票且不处于冷冻期或者前一天不持有股票且处于冷冻期的较大值 dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1]); } // 返回最后一天不持有股票的利润中的较大值 return Math.max(dp[n - 1][1], dp[n - 1][2]); } }