给定一个数组,它的第 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 。
这个题是122题的拓展。这里限定了交易次数k。我参考了Code_Ganker的解题思路。
下面说一下个人理解:
这里维护了两个变量:
- global[i][j]:是指在到达i天时,最多进行j次交易获得的最大利润。
- local[i][j]:是指到达i天时,最多可以进行j次交易。而且最后一次交易是在i天卖出的获得最大利润。
下面是维护两个变量的递归式:
g l o b a l [ i ] [ j ] = m a x ( g l o b a l [ i − 1 ] [ j ] , l o c a l [ i ] [ j ] ) global[i][j] = max(global[i-1][j],local[i][j]) global[i][j]=max(global[i−1][j],local[i][j])
这个公式很好理解,因为如果最后一次交易卖出的时间不是第i天,那么到达第i天获得的最大利润一定等于到达第i-1天获得的最大利润。
l o c a l [ i ] [ j ] = m a x ( g l o b a l [ i − 1 ] [ j − 1 ] + m a x ( d i f f , 0 ) , l o c a l [ i − 1 ] [ j ] + d i f f ) local[i][j] = max(global[i-1][j-1] + max(diff,0), local[i-1][j] + diff) local[i][j]=max(global[i−1][j−1]+max(diff,0),local[i−1][j]+diff)
global[i-1][j-1]表示在到达i-1天,一共进行了j-1次交易。加上max(diff,0)。如果j - (j-1)是赚钱的,就加上这次交易。如果不赚钱,那么就在第j天,当天买,当天卖。这样最后一次交易收益为0.
local[i-1][j]表示在到达第i-1天,一共进行了j次交易。从local[i][j-1]到local[i][j]。只需要在local[i][j-1]加上最有一次交易。就满足了最后一次交易是在第i天卖出的条件。
给出了递归式,就可以写程序了。
- 还需要注意 一种情况,如果可以交易的次数k超过了数组的长度。这个问题就可以变成一个无限次数操作的求最大股票利润的,参考买卖股票的最佳时机ll 的思路。
首先给出一个解题方法:
class Solution(object):
def maxProfit(self, k, prices):
def solvemaxProfit(prices):
res = 0
for i in range(1,length):
if prices[i] - prices[i-1] >0:
res += prices[i] - prices[i-1]
return res
if len(prices) <= 1:
return 0
length = len(prices)
if k >= length:
return solvemaxProfit(prices)
l = [[0]*(k+1) for i in range(length)]
g = [[0]*(k+1) for i in range(length)]
for i in range(length-1):
diff = prices[i+1] - prices[i]
for j in range(1,k+1):
l[i+1][j] = max(g[i][j-1] + max(diff,0),l[i][j] + diff)
g[i+1][j] = max(g[i][j],l[i+1][j])
return g[-1][-1]
可以将local矩阵和global矩阵降维。使用循环赋值这样可以节省空间开支。
- 此时要注意为保证循环赋值的正确性,内循环0-k必须采用到过来循环的操作。
class Solution(object):
def maxProfit(self, k, prices):
"""
:type k: int
:type prices: List[int]
:rtype: int
"""
def solvemaxProfit(prices):
res = 0
for i in range(1,length):
if prices[i] - prices[i-1] >0:
res += prices[i] - prices[i-1]
return res
if len(prices) <= 1:
return 0
length = len(prices)
if k >= length:
return solvemaxProfit(prices)
l = [0]*(k+1)
g = [0]*(k+1)
for i in range(length-1):
diff = prices[i+1] - prices[i]
for j in range(k,0,-1):
l[j] = max(g[j-1] + max(diff, 0),l[j]+diff)
g[j] = max(g[j], l[j])
return g[k]