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

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路

状态定义

一、很容易想到四种状态:

  • a.今天买入;
  • b.今天卖出;
  • c.昨天卖出,今天处于冷冻期,无法进行操作;
  • d.今天不操作,处于持有状态;

显然,a和d可以合并为持有状态,因此本题需要处理三种状态:「当天持有股票」、「当天不持有股票,卖出」、「当天不持有股票,处于冷冻期」。

二、状态表示

使用三个一维数组来表示这三种状态:

  • have[i]:第 i 天持有股票的最大收益;
  • sell[i] : 第 i 天售出股票的最大收益;
  • freeze[i] :第 i 天为冷冻期的最大收益;

状态转移

在这里插入图片描述

  • 对于持有状态 have,它可以由两种情况得到:

    第一种是「昨天就持有股票,今天不进行任何操作」,所以今天的收益等于昨天持有股票的收益,即 have[i] = have[i-1];
    第二种是「昨天不属于冷冻期,今天选择买入」,所以今天的收益等于冷冻期后的收益扣去今天的股票价格,即have[i] = freeze[i-1]-prices[i];

    要使得收益最大化,所以持有状态的收益就是两种情况下的最大收益,即 have[i] = max(have[i-1], freeze[i-1]-prices[i]);

  • 对于卖出状态,它只能由持有状态得到:「昨天持有股票,今天将其售出」,所以收益是昨天持有股票的收益加上今天的股票价格,即:sell[i] = have[i-1] + prices[i];

  • 对于冷冻期状态,它可以由两种情况得到:

    第一种是「昨天售出,进入冷冻期」,所以收益就是昨天售出股票后的收益,即freeze[i] = sell[i-1];
    第二种是「昨天是冷冻期,不持有任何股票,今天仍然不进行买入操作,所以保持在冷冻期」,那么收益就是昨天冷冻期的收益,即freeze[i] = freeze[i-1];

    同样地,要使得收益最大化,所以冷冻期的收益就是两种情况下的最大收益,即 freeze[i] = max(sell[i-1], freeze[i-1]);

初始化

  • have[0] = -prices[0]; :第0天要持有股票,那么一定需要选择买入价格为 prices[0] 的股票;
  • sell[0] = 0 :第0天要售出,且不持有股票,那么当天一定是买卖同一支股票,收益为 0;
  • freeze[0] = 0:第 0 天处于冷冻期,可以理解为不进行任何操作,即不买不卖,所以收益为 0。

最终的返回结果

最大收益一定是完成交易(即不持有股票) 的情况,所以返回 sell[n-1]freeze[n-1] 的最大值 。

易错点

  • 这道题可以多次买卖同一股票,因此初始化条件和之前的题目不一样,第 0 天处于 sell 和 freeze 状态也是合法状态,应该设为 0。
  • 对于持有状态,包含两种情况,也可以单独考虑,但稍显繁琐。

代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size() <= 1)  return 0;
        int n = prices.size();
        vector<int> have(n), sell(n), freeze(n);

        // 初始化
        have[0] = -prices[0];
        sell[0] = freeze[0] = 0;

        for(int i=1; i<n; ++i){
            have[i] = max(have[i-1], freeze[i-1]-prices[i]);
            sell[i] = have[i-1] + prices[i];
            freeze[i] = max(sell[i-1], freeze[i-1]);
        }
        return max(sell[n-1], freeze[n-1]);
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值