买卖股票的最jia时机III

123. 买卖股票的最佳时机 III

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 
     随后,在第 7 天(股票价格 = 1)的时候买入,在第 8  (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 

示例 2

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5  (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4    
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。   
     因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例 3

输入:prices = [7,6,4,3,1] 
输出:0 
解释:在这个情况下, 没有交易完成, 所以最大利润为 0

示例 4

输入:prices = [1]
输出:0

思路:

  解决这一题,请一定要有最初始问题:LeetCode买卖股票的最jia时机的模板基础!!掌握了一题就掌握了所有题!

  这一题是个困难题了。相应的我们不能再像之前两道题那样把模板当中的第二维删除,只用二维动态规划数组了。

还是先把模板拿出来:

dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][k][1]+prices[i])

dp[i][k][1]=max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i])

  首先对于这一题,第二维是不可以删除了,我们知道交易次数为2,则k的取值可以有0,1,2三个值,我们定义三维数组时在第二维就可以定义3的大小。

  其次定义base case时,原来我们只考虑0天不可能持有(dp[0][k][1]=-float(‘inf’)。现在我们还要加上交易次数为0不可能持有(dp[i][0][1]=-float(‘inf’))。反正说来说去,base case一共就是这么两类,“当第3维持有情况为1时,第1维或第2维都不能为0!”

  至于状态转移,原先只需要对i进行遍历:for i in range(1,lenth+1),现在还需要套一层对k的遍历: for k in range(1,3),紧接着就是完完全全的整套模板即可。

代码:

class Solution(object):

    def maxProfit(self, prices):

        #老规矩先写总模板做参考

        # dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][k][1]+prices[i])

        # dp[i][k][1]=max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i])

        lenth = len(prices)

        #定义动态规划三维数组

        # dp=[[[0,0]]*3 for _ in range(lenth+1)]#错误定义方式

        dp =[[[0]*2 for _ in range(3)] for _ in range(len(prices)+1)]

        #第一个要定义的base case  第0天却持有的情况

        for kk in range(3):

            dp[0][kk][1]=-float('inf')#

        #第二个要定义的base case 交易次数为0却持有的情况:

        for i in range(1,lenth+1):

            dp[i][0][1]=-float('inf')

        for i in range(1,lenth+1):#写上两层循环就可以套模板了

            for k in range(1,3):#k取值1到2嘛

                dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][k][1]+prices[i-1])

                dp[i][k][1]=max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i-1])

        return dp[lenth][2][0]#最终返回的是dp[lenth][2][0],非dp[lenth][0][0]

小结:

  这一题要定义维数组,定义方式为:dp =[[[0]*2 for _ in range(3)] for _ in range(len(prices)+1)]

其中2是第三维的大小,3是第二维k的大小,len(prices)+1是第一维i的大小。我们定义多维数组时,除了常数可以通过*n的方式去复制外,外层的数组必须通过for循环的方式去生成

   比如:[[0,0]]*3 [[0,0] for i in range(3)] 是不同的。因为前者并不是真正的复制,有可能涉及到“动一处而动全身”的出现,这一问题往往很难被发现(我就被错误的定义方式折磨到怀疑人生过)。因此定义多维数组,就记住要用for循环的方式!

    最后返回的是dp[lenth][2][0],代表lenth天,总交易次数为2,且不持有的最大利润,是符合dp定义含义的。交易次数是“总交易次数”,不是“剩余交易次数”,所以不要把2写成0

posted @   JunanP  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示