leetcode笔记--Best Time to Buy and Sell Stock with Cooldown

题目:难度(Medium)

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions:

You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day)
Example:

prices = [1, 2, 3, 0, 2]
maxProfit = 3
transactions = [buy, sell, cooldown, buy, sell]
Tags:Dynamic Programming

分析:本题与Best Time to Buy and Sell Stock II 唯一的区别是在卖出股票后需要间隔至少一天才能卖出,即卖出股票后有一天的冷却期,所以本题中股票有3种状态:buy, sell, cooldown,而cooldown的表现也是手中未持有股票,因此它与sell表现相同,都是手中没有股票即“卖掉股票”。设sell[i]表示第i天手中未持有股票获得的最大利润,buy[i]表示第i天手中有股票获得的最大利润:

        那么sell[i]有2种情况:
        1.第i-1天手中有股票,在第i天卖出:buy[i-1]+prices[i],
        2.第i-1天手中没有股票,第i天继续前一天的状态:sell[i-1]
        因此,对应的状态转移方程为:sell[i] = max(buy[i-1]+prices[i], sell[i-1])
        buy[i]也有2种情况:
        1.第i-1天持有股票,今天继续昨天的状态:buy[i-1]
        2.第i-1天未持有股票,但有可能是因为第i-1天卖出了股票,而由于冷却期的限制,第i天是不能买入的即无法持有股票,因此应该考虑第i-2天的状态,若第i-2天未持有股票,那么第i天就是sell[i-2]-prices[i],这就包含了在第i-2天卖出,第i-1天冷却,在第i天买进的这种情况,也包含了在第i-2天就是冷却状态,第i-1天继续维持第i-2天的状态,在第i天买进的情况
        因此,对应的状态转移方程为:buy[i] = max(sell[i-2]-prices[i], buy[i-1])
        因此,sell[-1]即为所求,时间复杂度是O(n)

代码实现:

def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
	空间复杂度是O(n)
        """
        n = len(prices)
        if n < 2:
            return 0
            
        dpsell = [0]*n
        dpbuy = [0]*n
        #初始化
        dpsell[0], dpbuy[0] = 0, -prices[0]
        #dpbuy[1] = max(buy[0], -prices[1])表示第1天买进,第2天继续持有,或者第1天不买也不卖,第二天买进
        dpsell[1], dpbuy[1] = max(dpbuy[0]+prices[1], dpsell[0]), max(dpbuy[0], -prices[1])
        for i in range(2, n):
            dpsell[i] = max(dpsell[i-1], dpbuy[i-1]+prices[i])
            dpbuy[i] = max(dpbuy[i-1], dpsell[i-2]-prices[i])
        return dpsell[-1]

空间复杂度为O(n)


由于i只依赖于i-1和i-2,我们还可以做进一步优化,在O(1)的空间复杂度完成算法。

代码实现:

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
	空间复杂度为O(1)
        """
        n = len(prices)
        if n < 2:
            return 0
        
        #preSell, preBuy = 0, -prices[0]
        #curSell, curBuy = max(preSell, preBuy+prices[1]), max(preBuy, -prices[1])
        preSell = 0
        curSell = max(preSell, -prices[0]+prices[1])
        curBuy = max(-prices[0], -prices[1])
        for i in range(2,n):
            tmp = curSell
            curSell = max(curSell, curBuy+prices[i])
            curBuy = max(curBuy, preSell-prices[i])
            preSell = tmp
        return curSell

参考:

        https://segmentfault.com/a/1190000004193861

        http://www.cnblogs.com/grandyang/p/4997417.html

        http://bookshadow.com/weblog/2015/11/24/leetcode-best-time-to-buy-and-sell-stock-with-cooldown/


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值