给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。
注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [2,4,1], k = 2
输出: 2
解释: 在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
示例 2:
输入: [3,2,6,5,0,3], k = 2
输出: 7
解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。
解题思路
这是之前问题的扩展。
Leetcode 121:买卖股票的最佳时机(最详细的解法!!!)
Leetcode 122:买卖股票的最佳时机II(最详细的解法!!!)
Leetcode 123:买卖股票的最佳时机III(最详细的解法!!!)
因为这个问题中有最多k笔交易的限制,所以我们不难想到通过123
号问题的解法来解,但是这里有一个问题,就是当2k>len(prices)
的时候我们需要开辟很大的存储空间,在leetcode
上提交的话会出现内存溢出的错误。怎么办?当2k>len(prices)
的时候,其实可以将问题转化为122
号问题,也就是交易次数不限。为什么是2k
?因为买和卖是两个操作。
好,现在我们的思路就很明确,当2k>len(prices)
的时候,我们通过贪心来解决;当2k<=len(prices)
的时候,我们通过动态规划来解决。我们也可以将2k=len(prices)
通过贪心解决,其实是一样的,这是一个临界问题。
class Solution:
def maxProfit(self, k, prices):
"""
:type k: int
:type prices: List[int]
:rtype: int
"""
p_len = len(prices)
if k >= p_len//2:
return self.greedy(prices)
buy, sell = [-prices[0]]*k , [0]*(k+1)
for p in prices[1:]:
for i in range(k):
buy[i] = max(buy[i], sell[i-1]-p)
sell[i] = max(sell[i], buy[i]+p)
return max(sell)
def greedy(self, prices):
res = 0
for i in range(1, len(prices)):
if prices[i] > prices[i-1]:
res += prices[i] - prices[i-1]
return res
这里需要注意的就是buy
的初始化,对sell
的初始化我们使用了k+1
,为什么?为了避免k=0
的时候此时sell
为空,我们无法调用max
函数。其余的地方都是顺理成章的。
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!