【LeetCode笔记】309. 最佳买卖股票时机含冷冻期(Java、动态规划)

题目描述

  • 股票系列!这次加入了冷冻期要素,需要考虑更多的状态
    在这里插入图片描述

思路 && 代码

  • 每天,都有三个状态:开一个 dp = int[n][3] 二维数组
  • 主要思路…就是理解几种状态,以及转移的思路(见注释)
  • 时空复杂度:O(n)、O(n)
class Solution {
    public int maxProfit(int[] prices) {
        // 对每一天,存储三个状态:
        // 0)持有(昨天就持有 or 今天买入(那么昨天肯定没卖))
        // 1)不持有,没卖(昨天肯定也没有)
        // 2)不持有,但是是今天卖的(昨天肯定持有)
        int[][] dp = new int[prices.length][3];
        // 初始化:
        dp[0][0] = -prices[0]; 
        dp[0][1] = 0; 
        dp[0][2] = 0; 
        for(int i = 1; i < prices.length; ++i) {
            // 1)今天持有,那么昨天:【本就持有】or【不持有(今天再买)】
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i]);  
            // 2)今天不持有,也没卖,那么昨天:【不持有且没卖】or【卖了导致不持有】
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][2]); 
            // 3)今天卖了,导致不持有。那么昨天:一定【持有】
            dp[i][2] = dp[i - 1][0] + prices[i]; 
        }

        // 最后一天的两种【不持有状态】,取 max
        return Math.max(dp[prices.length - 1][1], dp[prices.length - 1][2]); 
    }
}
  • 无注释版
class Solution {
    public int maxProfit(int[] prices) {
        int[][] dp = new int[prices.length][3];
        dp[0][0] = -prices[0]; 
        dp[0][1] = 0; 
        dp[0][2] = 0; 
        for(int i = 1; i < prices.length; ++i) {
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i]);  
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][2]); 
            dp[i][2] = dp[i - 1][0] + prices[i]; 
        }

        return Math.max(dp[prices.length - 1][1], dp[prices.length - 1][2]); 
    }
}

二刷

  • 代码量少的一,就 9 行!但是难度还是有。
  • 我觉得难点在于状态的考虑,但是理清状态之后,或许就很难做错了= =
class Solution {
    public int maxProfit(int[] prices) {
        // 难点:如何思考出三种状态,其全面性
        // Part 1: 初始化
        int[][] dp = new int[prices.length][3]; // 每一天,存储三种状态:
        dp[0][0] = -prices[0]; // 1)持有,今天买的
        dp[0][1] = 0; // 2)不持有,并不是因为今天卖了
        dp[0][2] = 0; // 3)不持有,因为今天卖了(当然,dp[0][2] 是初始化,就当作卖了个寂寞)
        for(int i = 1; i < prices.length; i++) {
            dp[i][0] = Math.max(dp[i - 1][1] - prices[i], dp[i - 1][0]); // 今天有:今天卖,昨天没卖 or 昨天买了
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][2]); // 今天不持有:昨天卖了 or 昨天就不持有
            dp[i][2] = dp[i - 1][0] + prices[i]; // 今天卖了,只能是昨天持有
         }
        // 不持有状态,二选一吧!
        return Math.max(dp[prices.length - 1][1], dp[prices.length - 1][2]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值