算法训练营DAY50|309.最佳买卖股票时机含冷冻期 、714.买卖股票的最佳时机含手续费

买卖股票的最后一期了,第一道含冷冻期难一点,第二道含手续费不难,完全就是之前买卖股票II的模板。

309. 最佳买卖股票时机含冷冻期 - 力扣(LeetCode)https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/这道题难在需要定义更多的dp数组针对第二维状态的定义,它不同于之前讲的那些题。

dp数组的含义:dp【i】【0】还是和之前一样,它代表了持有股票的状态,即包含了买入股票和以前买入现在持有的一个状态。dp【i】【1】我们将其定义为卖出股票后的状态即它是仅代表卖出去股票之后且还未购买新股票的一个状态。dp【i】【2】代表了第i天当天卖出股票的状态,dp【i】【3】代表了卖出股票后的那天冷冻期。我们把之前能够同时表示卖出股票和卖出股票后未持有股票的状态拆分开来,分成了单独的两部分,这是因为买卖股票有一天冷冻期,而我们需要明确确定冷冻期是哪一天,这时我们是需要知道哪一天卖出了股票才能确定冷冻期,这在后面的递推公式也能展示出来。

递推公式:dp【i】【0】根据含义分析一下,它可以由什么状态推出来?持有股票的前一天(也就是继承前一天),冷冻期的后一天再买股票,和冷冻期之后的某一天购买股票,所以说可以由三个状态推出来。

dp【i】【0】=max(dp【i-1】【0】,dp【i-1】【3】-prices【i】,dp【i-1】【1】-prices【i】)

值得关注的是,dp【i-1】【3】-prices【i】,他确实代表了冷冻期的后一天购买股票,只不过这冷冻期后一天购买股票,用的是冷冻期时候所拥有的钱。

dp【i】【1】同样也是由它的前一天的状态和前一天是冷冻期,第一种情况推出不用多说了,很正常的推出,第二种就是新加入的冷冻期概念由于该天的前一天是冷冻期不能购买股票,所以如果当天也没购买那自然就是卖出后未持有股票的状态。

dp【i】【2】是卖出股票的状态,那只能一种情况dp【i-1】【0】+prices【i】也就是持有股票的情况下卖出去。

dp【i】【3】是冷冻期也是一种情况,dp【i-1】【2】,冷冻期啥也干不了所以也就是卖出股票时候有多少钱就是多少钱。

dp数组初始化:dp【0】【0】=-prices【0】就是第一天买股票,就是这么多钱。

其余的状态我们初始化多少呢?其实其他状态在第一天都是非法的状态,我们可以这样想,第一天买第一天卖那肯定就是不赚钱就是0,而不持有股的状态也是0,冷冻期和卖出股票时候一样所以也是0。更靠谱一点的数学推理,我们可以带入递推公式,按情况来初始化,这一方面大家也可以把数据自己带入,试一试,也就知道了第一次初始化应该为多少。

遍历顺序:是正常的从前向后

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>>dp(prices.size(),vector<int>(4,0));
        dp[0][0]=-prices[0];
        for(int i=1;i<prices.size();i++){
            dp[i][0]=max(dp[i-1][0],max(dp[i-1][3]-prices[i],dp[i-1][1]-prices[i]));
            dp[i][1]=max(dp[i-1][1],dp[i-1][3]);
            dp[i][2]=dp[i-1][0]+prices[i];
            dp[i][3]=dp[i-1][2];
        }
        return max(dp[prices.size()-1][1],max(dp[prices.size()-1][2],dp[prices.size()-1][3]));
    }
};

这道题因为状态多,要确定每个状态的含义,只有确定清楚才能够解出题解。


714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)icon-default.png?t=N0U7https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/这道题也是可以重复买卖股票的题,与买卖股票II的唯一区别仅在于每次买卖需要交一次手续费,这其实就购买股票时候加上一次手续费,就可以了,代码方面没有大改动,不懂得去看上两篇文章。

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        vector<vector<int>>dp(prices.size(),vector<int>(2,0));
        dp[0][0]=-prices[0]-fee;
        for(int i=1;i<prices.size();i++){
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i]-fee);
            dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i]);
        }
        return dp[prices.size()-1][1];
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学习算法的杨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值