LeetCode-309. 最佳买卖股票时机含冷冻期

LeetCode-309. 最佳买卖股票时机含冷冻期 (中等)

题目地址:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/

1. 题目描述及示例

      给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​
      设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

      卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
      注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例一:

输入: prices = [1,2,3,0,2]
输出: 3
解释:对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

示例二:

输入: prices = [1]
输出: 0

2. 题解和代码实现

      最大利润,从最大来看显然我们可以采用动态规划法进行实现。但是,我们应该注意该题有一定的限制的条件,正是有这些限制条件,我们可以发现,会有一些状态。我们采用dp[i] 来进行代表这一天结束后,所能收到的最大利润。显然对这一天结束有着以下状态:

  1. 当前拥有一支股票,那么这一天的结束的最大利润,由上一天来决定;1)上一天本来就有一支股票,2)上一天结束的时候没有股票,那么上一天一定没有卖出(如果上一天卖出,当天无法进行购买),所以为当天进行买入。
	dp[i][0] = max(dp[i-1][0],dp[i-1][2]-prices[i]);
  1. 当前没有股票,且在这天结束,会有后一天的冷冻期(必然是今天进行了卖出)。
	dp[i][1] = dp[i-1][0] + prices[i];
  1. 当前没有股票,且没有后一天的冷冻期;那么会有:1)上一天没有股票,且今天处于冷冻期;2)没有股票也没有在冷冻期,但是也没有进行买入。
	dp[i][2] = max(dp[i-1][1],dp[i-1][2]);

代码实现(C++ 2022-4-24)

	class Solution {
public:
    int maxProfit(vector<int>& prices) {
        // 1. 卖出股票后,第二天无法进行购买,这其实是所谓的冷冻期
        // 2. 必须在再次购买之前进行卖出,卖出之后才能进行购买

        // 我们的状态是,1.当前有股票 2. 当前没有股票,且处于冷冻期 3. 当前没有股票且不处于冷冻期

        // 定义dp[i][0] dp[i][1] dp[i][2] 分别表示这三种状态

        // 当前位置的1状态最后的收入,两种可能1.本来有股票 2.一开始没,但是进行了买入
        // dp[i][0] = max(dp[i-1][0],dp[i-1][2]-prices[i])  

        // 针对2状态 ,肯定是上一天进行了卖出(卖出肯定是有股票的情况下进行了卖出)
        // dp[i][1] = dp[i-1][0]+prices[i]

        // 针对3状态, 表明当天没有任何操作。上一天处于冷冻期;上一天处于非冷冻期
        // dp[i][2] = max(dp[i-1][1],dp[i-1][2])
       if(prices.empty()){
           return 0;
       }
    //    vector<vector<int>> dp(prices.size(), vector<int>(3));
    //    dp[0][0] = -prices[0];
    //    dp[0][1] = 0;
    //    dp[0][2] = 0;
        
    //     for(int i=1;i<prices.size();i++){
    //         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][1],dp[i-1][2]);
    //     }
    //     return max(dp[prices.size()-1][1],dp[prices.size()-1][2]);

        // 进行空间的改进
        int dp_0 = -prices[0];
        int dp_1 = 0;
        int dp_2 = 0;
        for(int i=1;i<prices.size();i++){
            int new_dp_0 = max(dp_0,dp_2-prices[i]);
            int new_dp_1 = dp_0 + prices[i];
            int new_dp_2 = max(dp_1,dp_2);
            dp_0 = new_dp_0;
            dp_1 = new_dp_1;
            dp_2 = new_dp_2;
        }
        return max(dp_1,dp_2);
    }
};

3. 总结

      主要在于三种状态的把握,这三种状态进行一个很好的把握,对本题的求解会有一个新的认识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zh-yi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值