leetcode 力扣 309 买卖股票的最佳时机含冷冻期

119 阅读2分钟

动态规划

状态定义

题目要求卖出股票的下一天,不能再买入股票。针对这个要求,我们定义两个状态,表示当天的股票状态:

  • 状态0:非持有股票(但不是今天卖出导致非持有,可以是上一天卖出,上上天卖出,或者一直没买过)
  • 状态1:持有股票(在状态0(注意是上一天的状态),买入股票(比如9号卖出,11号买入);或者昨天持有股票,今天不卖)

状态1中,可以看出今天持有股票的状态,均不是由昨天卖出股票,今天买入所转移而来的,这样就避免了在冷冻期买入股票。

  • 接着我们可以再使用一个状态2表示,今天卖出股票。

dp数组定义

有了上述三个状态后,我们就可以来定义dp数组。

  • dp[i][0]:第i天非持有股票时,所具有的最大收益
  • dp[i][1]:第i天持有股票时,所具有的最大收益
  • dp[i][2]:第i天卖出股票时,所具有的最大收益

dp数组初始化

第一天只能买入

  • dp[0][0] = 0
  • dp[0][1] = -prices[0]
  • dp[0][2] = 0

状态如何转移?

  • dp[i][0](今天不持有股票,最大收益是多少?):
  1. 昨天不持有,今天继续不买入;
  2. 昨天卖出股票。
    也就是上一天dp[i - 1][0]dp[i - 1][2]中的最大值。
  • dp[i][1](今天持有股票,最大收益是多少?):
  1. 昨天持有,今天不卖;
  2. 昨天不持有,今天买入。
    也就是上一天dp[i - 1][1]dp[i - 1][0] - prices[i](注意是减,买入股票要花钱,是负收益)中的最大值。
  • dp[i][2](今天卖股票,最大收益是多少?):今天卖出股票。dp[i - 1][1] + prices[i]

填完dp表后,返回dp[n - 1][0]dp[n - 1][2]中的最大值,也就是手中没有股票时的最大收益。

由右下角往上反推,就能找到最佳时机路径:买入->卖出->冷冻->买入->卖出 1.jpeg

class Solution {
    public int maxProfit(int[] prices) {
        int n = prices.length;
        if (n == 1) {
            return 0;
        }

        int[][] dp = new int[n][3];
        dp[0][0] = 0;
        dp[0][1] = -prices[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]);
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
            dp[i][2] = dp[i - 1][1] + prices[i];
        }

        return Math.max(dp[n - 1][0], dp[n - 1][2]);
    }
}