买卖股票的最jia时机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。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了