Leetcode: Best Time to Buy and Sell Stock

这一篇总结leetcode里关于股票的题目,都是用dynamic programming

  1. Best Time to Buy and Sell Stock
    https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/
    只能操作一次
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int maxp = 0;
        int minbuy = INT_MAX;
        for(int i = 0; i < prices.size(); i++)
        {
            minbuy = min(minbuy , prices[i]);
            maxp = max(maxp , prices[i] - minbuy );
        }     
        return maxp ;
    }
};
  1. Best Time to Buy and Sell Stock II
    https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/
    可以操作多次
    这个题最优解很简单,但不是那么容易捋清楚,
    主要考虑两种模式:
    一:a < b < c < d (monotone increase)
    res = d - a = b - a + c - b + d - c

二:a < b > c < d (non monotone increase)
res = b - a + d - c (必定> d - a)

所以结果就是 if (prices[i+1] > prices[i]) res =+ prices[i+1] - prices[i];

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int res = 0;
        for(int i = 0; i+1 < prices.size(); i++)
        {
            res += max(0, prices[i+1] - prices[i]);
        }
        return res;
    }
};
  1. Best Time to Buy and Sell Stock III
    https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/
    允许最多两次操作
    这个写法也很精简,但是想法并不简单,或者说并不容易想清楚,这个解法是从leetcode discuss上来的(meng789987)
    我理解的大概的思想:每次交易都试图找minbuy price,同时试图找maxprofit price就像只允许交易一次那样,since允许两次交易,第二次交易,需要把第一次交易的maxprofit包含进去,那么第二次交易的maxprofit就是最后打答案。
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int maxp1 = 0, maxp2 = 0;
        int minbuy1 = INT_MAX, minbuy2 = INT_MAX;
        
        for(int i = 0; i < prices.size(); i++)
        {
            minbuy1 = min(minbuy1, prices[i]);
            maxp1 = max(maxp1, prices[i] - minbuy1);
            minbuy2 = min(minbuy2, prices[i] - maxp1);
            maxp2 = max(maxp2, prices[i] - minbuy2);
        }
        
        return maxp2;       
    }
};
  1. Best Time to Buy and Sell Stock IV
    https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/description/
    允许最多k次
    这个解法是上面的延申,但是k = 1000000000 时会有std::bad_alloc
    可能space不够优化?
class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if(prices.size() < 1) return 0;
        
        vector<int>minbuy(k+1, prices[0]);
        vector<int>maxp(k+1, 0);
         
        for(int i = 1; i < prices.size(); i++)
        {
            for(int j = 1; j <= k; j++)
                
            {
                minbuy[j] = min(minbuy[j], prices[i] - maxp[j-1]);
                maxp[j] = max(maxp[j], prices[i] - minbuy[j]);
            }
        }
        
        return maxp[k];
    }
};

309 Best Time to Buy and Sell Stock with Cooldown
After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)
Note: cooldown only happens after sell.
这个题是个非常典型的dynamic programming。
dynamic programming的关键是找transition function.
buy[i]是记录如果i day买入股票的最大的profit (所以,buy[0]=-prices[0])
sell[i]是记录如果i day卖掉股票的最大的profit (所以,sell[0]=0)

buy[i] = max(buy[i-1], sell[i-2] - prices[i])
sell[i] = max(sell[i-1], buy[i-1]+prices[i])
iday只有三种操作,卖或者买或者什么也不做

对于buy[i], 如果iday不买,如果iday买,找出最大。
不买,就是buy[i-1];
买就是sell[i-2]-prices[i], 因为有cooldown,所以必须是前两天的sell
对于sell[i], 如果iday不卖,如果iday卖,找出最大。
不卖,就是sell[i-1];
卖就是buy[i-1]+prices[i],卖和买之间并没有cooldown

    int maxProfit(vector<int>& prices) {
        int size = prices.size();
        if(size < 1) return 0;
        
        vector<int>buy(size);
        vector<int>sell(size);
        
        buy[0] = -prices[0];
        sell[0] = 0;
        
        for(int i = 1; i < size; i++)
        {
            buy[i] = max(buy[i-1], (i >= 2 ? sell[i-2] : 0) - prices[i]);
            sell[i] = max(sell[i-1], buy[i-1] + prices[i]);
        }      
        return sell[size - 1];
    }
};

这个空间复杂度是O(n),
但是buy or sell只跟前面的买和卖有关,可以继续优化

        int prebuy = - prices[0];
        int presell = 0, prepresell = 0;
        int buy = 0, sell = 0;
        
        for(int i = 1; i < size; i++)
        {
            int tmp = presell;
            buy = max(prebuy, (i >= 2 ? prepresell : 0) - prices[i]);
            sell = max(presell, prebuy + prices[i]);
            prebuy = buy;
            prepresell = tmp;
            presell = sell;         
        }    
        return sell;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值