• 309. Best Time to Buy and Sell Stock with Cooldown


    今天又做到了一道买卖股票 309. Best Time to Buy and Sell Stock with Cooldown 的题,我思考了一会没做出来,参考了别人的解答才理解的。

    这道题相比之前一道类似的题 122. Best Time to Buy and Sell Stock II 的区别就是加上了一个cooldown的限制条件,就是卖完股票的接下来一天不能再接着买,至少需要等待一天之后才能买。中间不能参与交易的那些日期就称为所谓的“cooldown”时期,现在问最大的收益是多少?

    这道题我们想一下,对于每一天,有几种可能的状况:

    • 买入股票
    • 卖出股票
    • cooldown(啥都不做,没法交易)

    我们想,影响我们某一天为止的累计收益其实只有买入和卖出操作,而且当我们买入股票时,由于花钱了,累计收益肯定是减少的,当我们卖出股票时,由于挣钱了,累计收益肯定是增加的。最后是要计算最大的累计收益,所以我们只需要在每次卖出股票的时候更新我们的最大收益。

    由于这道题是要用dp做的,所以我们设置两个数组buy和sell,它们的作用如下:

    • buy[i]表示第i天的状况是“买入股票”的最大累计收益
    • sell[i]表示第i天的状况是“卖出股票”的最大累计收益

    想一下buy[0]是多少?
    buy[0]指的是第0天买入股票对应的最大收益,有人可能会说,第0天买入股票没有收益呀,不对,你买入了股票,说明你花钱了,你目前的收益是负的,以后无论你什么时候卖出去,都是在当前的负的基础上加。所以buy[0] = -prices[0],同理buy[1] = -prices[1]

    然后再想一下sell[0]是多少?
    第0天就卖?之前都没买怎么去卖,所以sell[0] = 0,sell[1]就不同了,如果prices[1] > prices[0]的话,sell[1]应该等于prices[1] - prices[0],否则还是等于0。

    我们想一想,buy[i]的值跟之前哪些值有关?我们分2种情况讨论:

    • 之前含有未完成的交易,如果之前一天执行的也是买入操作,那么如果换成今天买入,累计收益会不会增加呢?
      那么这取决于什么呢?就是昨天跟今天买入的价格哪个更便宜,注意,由于买入时累计收是益减少的,所以其实比的是谁减少的更少,即花的钱比较少,这样收益就更大。
      有人说你怎么不说前天也执行的是“买入”操作呢?因为我们在计算buy[i-1]的时候就考虑过buy[i-2],所以我们在计算buy[i]的时候只考虑buy[i-1],而不考虑buy[i-2],换句话说,这种情况下我们只需要和前一天做比较。

    • 之前不含有未完成的交易,那么今天要买入,昨天就必须是cooldown,当然前天也可能是cooldown,但我们这里需要考虑的是,如果前天卖过股票,那么当前的最大收益是多少?这个就很简单,因为买入股票累计收益是减少的,所以今天的累计收益是sell[i-2]-prices[i]。
      有人可能又要问了,既然你说前天也可能是cooldown,那么你怎么不考虑sell[i-3]-prices[i],还是那句话,计算sell[i-2]的时候考虑过sell[i-3]。

    综上,我们得到第一个状态转移方程:

    delta = price[i] - price[i - 1]
    buys[i] = max(sells[i - 2] - prices[i], buys[i - 1] - delta)
    

    同样,我们再想想,sell[i]的值跟之前哪些值有关?我们分2种情况讨论:

    • 之前含有完成的交易,如果之前一天执行的也是卖出操作,那么如果换成今天卖出,累计收益会不会增加呢?
      那么这取决于什么呢?就是昨天跟今天卖出的价格哪个更贵。所以我们这里需要考虑sells[i - 1] + delta的值
    • 之前含有未完成的交易,这个简单,就是单纯的卖出去,累计收益只需要加上这一天卖出去的价格。

    综上,我们得到第二个状态转移方程:

    delta = price[i] - price[i - 1]
    sells[i] = max(buys[i - 1] + prices[i], sells[i - 1] + delta) 
    

    如果你仔细观察,你会发现这和上面的逻辑是一样的。

    于是我们写出如下代码:

    class Solution {
    public:
        int maxProfit(vector<int>& prices) {
            int len = prices.size();
            if(len==0 || len==1) return 0;
            
            vector<int> buy(len, 0);//buy[i]表示第i天选择买入股票所得最大收益
            vector<int> sell(len, 0);//sell[i]表示第i天选择卖掉股票所得最大收益
            
            buy[0] = -prices[0]; buy[1] = -prices[1];
            sell[1] = max(0, prices[1]-prices[0]);
            int max_profit = max(0, sell[1]);
            for(int i = 2; i < len; i++){
                int delta = prices[i] - prices[i-1];
                sell[i] = max(sell[i-1]+delta, buy[i-1]+prices[i]);
                buy[i] = max(buy[i-1]-delta, sell[i-2]-prices[i]);
                max_profit = max(max_profit, sell[i]);
            }
            
            return max_profit;
        }
    };
    

    点击submit

    芜湖,起飞!

    参考文章: https://blog.csdn.net/aishangyutian12/article/details/51881654

    只有0和1的世界是简单的
  • 相关阅读:
    JavaScript 的历史
    阿里面试题:
    DBA_Oracle基本体系架构(概念)
    java内存管理机制
    HashMap的内部实现机制,Hash是怎样实现的,什么时候ReHash
    HashMap实现原理分析
    堆栈
    数据结构:HDU 2993 MAX Average Problem
    数学(欧拉函数):UVAOJ 11426 GCD
    搜索(DLX):HOJ 1017
  • 原文地址:https://www.cnblogs.com/nullxjx/p/14364920.html
Copyright © 2020-2023  润新知