博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【leetcode】best time to buy and sell stocks(i, ii, iii, iv, v)
阅读量:6823 次
发布时间:2019-06-26

本文共 4516 字,大约阅读时间需要 15 分钟。

i.只允许一次交易

  • 思路:从前向后遍历数组,记录当前出现过的最低价格,作为买入价格,并计算以当天价格出售的收益,作为可能的最大收益,整个遍历过程中,出现过的最大收益就是所求。

    class Solution(object):   def maxProfit(self, prices):       if len(prices) < 2:           return 0       curMin = prices[0]       maxPro = 0       for i in range(len(prices)):           if curMin > prices[i]:               curMin = prices[i]           if maxPro < prices[i] - curMin:               maxPro = prices[i] - curMin       return maxPro

ii.允许多次购买

  • 思路:这是最理想的情况,即可以在低价购入高价抛出,只要前一天的价格低于后一天,这个差价即为可获得的利润。贪心的思路。

    class Solution(object):   def maxProfit(self, prices):       """       :type prices: List[int]       :rtype: int       """       if len(prices) < 2:           return 0       maxPro = 0       for i in range(1, len(prices)):           if prices[i] > prices[i - 1]:               maxPro += prices[i] - prices[i - 1]       return maxPro

iii 至多允许两次购买

  • 思路:dp

    • 对于第i天而言,获得的最大利润为前i天进行一次交易的最大利润prePro[i]+第i天后进行一次交易的最大利润postPro[i]。之后遍历求max{prePro[i] + postPro[i]},(0 <= i <= i - 1)即可。

    • prePro[i]和postPro[i]可以根据情况i的思路求解出来。

class Solution(object):        def maxProfit(self, prices):            if len(prices) < 2:                return 0            n = len(prices)        prePro = [0] * n        postPro = [0] * n        curMin = prices[0]        for i in range(1, n):            if curMin > prices[i]:                curMin = prices[i]            prePro[i] = max(prePro[i - 1], prices[i] - curMin)        curMax = prices[n - 1]        for i in range(n - 2, 0, -1):            if curMax < prices[i]:                curMax = prices[i]            postPro[i] = max(postPro[i + 1], curMax - prices[i])        maxPro = 0        for i in range(n):            maxPro = max(maxPro, prePro[i] + postPro[i])        return maxPro

iv:ii和iii的延伸,至多k次购买

事实上iii是其中k = 2的情况。而ii是k >= len(prices)的情况。

这道题的思路很自然地能想到用dp。但是一个状态方程是有问题的。一开始自己并没有意识到,于是犯错了。
以下摘自

分析:特殊动态规划法。传统的动态规划我们会这样想,到第i天时进行j次交易的最大收益,要么等于到第i-1天时进行j次交易的最大收益(第i天价格低于第i-1天的价格),要么等于到第i-1天时进行j-1次交易,然后第i天进行一次交易(第i天价格高于第i-1天价格时)。于是得到动规方程如下(其中diff = prices[i] – prices[i – 1]):

profiti = max(profiti – 1, profiti – 1 + diff)
看起来很有道理,但其实不对,为什么不对呢?因为diff是第i天和第i-1天的差额收益,如果第i-1天当天本身也有交易呢(也就是说第i-1天刚卖出了股票,然后又买入等到第i天再卖出),那么这两次交易就可以合为一次交易,这样profiti – 1 + diff实际上只进行了j-1次交易,而不是最多可以的j次,这样得到的最大收益就小了。

那么怎样计算第i天进行交易的情况的最大收益,才会避免少计算一次交易呢?我们用一个局部最优解和全局最有解表示到第i天进行j次的收益,这就是该动态规划的特殊之处。

用locali表示到达第i天时,最多进行j次交易的局部最优解;用globali表示到达第i天时,最多进行j次的全局最优解。它们二者的关系如下(其中diff = prices[i] – prices[i – 1]):

locali = max(globali – 1 , locali – 1 + diff)

globali = max(globali – 1, locali)
locali和globali的区别是:locali意味着在第i天一定有交易(卖出)发生,当第i天的价格高于第i-1天(即diff > 0)时,那么可以把这次交易(第i-1天买入第i天卖出)跟第i-1天的交易(卖出)合并为一次交易,即locali=locali-1+diff;当第i天的价格不高于第i-1天(即diff<=0)时,那么locali=globali-1+diff,而由于diff<=0,所以可写成locali=globali-1。globali就是我们所求的前i天最多进行k次交易的最大收益,可分为两种情况:如果第i天没有交易(卖出),那么globali=globali-1;如果第i天有交易(卖出),那么globali=locali。

class Solution(object):

def maxProfit1(self, prices):        """        :type prices: List[int]        :rtype: int        """        if len(prices) < 2:            return 0        maxPro = 0        for i in range(1, len(prices)):            if prices[i] > prices[i - 1]:                maxPro += prices[i] - prices[i - 1]        return maxPro    def maxProfit(self, k, prices):        n = len(prices)        if n < 2:            return 0        if k >= n:            return self.maxProfit1(prices)        profit1 = [[0] * (k + 1)] * n        profit2 = [[0] * (k + 1)] * n        diff = [0] * n        for i in range(1, n):            diff[i] = prices[i] - prices[i - 1]            for j in range(1, k + 1):                profit1[i][j] = max(profit2[i - 1][j - 1], profit1[i - 1][j] + diff[i])                profit2[i][j] = max(profit1[i][j], profit2[i - 1][j])        return profit2[n - 1][k]

v:with cooldown:

  • 思路:dp。此题又回到了任意多次交易的情况。每天的利润不仅与前一天相关,还与前一天是否相关(因为若前一天sell,第二天是不允许buy的)。我们定义两个数组:buy和sell来标记两种状态。

    • buy[i]:若第i天时手头有股票可获得的最大利润;

    • sell[i]:若第i天时手头没有股票,可获得的最大利润。

      selli] = max(buy[i-1] + prices[i, selli-1)
      buyi] = max(buy[i-1,selli - 2] - prices[i)

    • sell[-1]即为所求

      代码:

class Solution(object):

def maxProfit(self, prices):        if len(prices) < 2:            return 0        n = len(prices)        sellPro = [0] * n        buyPro = [0] * n        sellPro[0] = 0        buyPro[0] = 0 - prices[0]        sellPro[1] = max(prices[1] - prices[0], 0)        buyPro[1] = max(-prices[0], -prices[1])                for i in range(2, n):            sellPro[i] = max(buyPro[i - 1] + prices[i], sellPro[i - 1])            buyPro[i] = max(buyPro[i - 1], sellPro[i - 2] - prices[i])                return sellPro[-1]

转载地址:http://twgzl.baihongyu.com/

你可能感兴趣的文章
Android项目依赖于第三方库(非jar包文件)
查看>>
cas HttpServletRequestWrapperFilter
查看>>
JavaWeb 三层框架
查看>>
Mac 下 SVN 的使用
查看>>
Android APK反编译教程(带工具)
查看>>
Windows学习总结(12)——Windows 10系统开始运行-cmd命令大全
查看>>
【树形dp】vijos P1180 选课
查看>>
实验三
查看>>
Groovy
查看>>
滑动窗口的最大值
查看>>
[转]BT常用渗透命令
查看>>
面向.Net程序员的前端优化
查看>>
HTTPS到底是个什么鬼?
查看>>
Yii框架中ActiveRecord使用Relations
查看>>
leetcode 55.跳跃游戏
查看>>
flexPaper +swftools实现文档在线阅读
查看>>
分形树的绘制
查看>>
loadrunner请求中有汉字 如何编码
查看>>
java数据结构 • 面向对象 • 异常 • 随机数·时间
查看>>
springmvc 实现pc端手机端适配(同一个请求根据不同客户端展示不同界面)
查看>>