123.买卖股票的最佳时机III
思路
-
dp数组含义:这道题和之前的买卖股票不同的地方在于,最多可以完成两笔交易。所以对于第i天可以有以下的四种状态:
- 没有操作
- 第一次持有股票
- 第一次不持有股票
- 第二次持有股票
- 第二次不持有股票
dp[i][j]
中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]
表示第i天状态j所剩最大现金。需要注意:
dp[i][1]
,表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票。 -
递推公式:
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i])
dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + prices[i])
dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i])
dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i])
-
初始化:第一次买入、第二次买入初始化为
-prices[0]
,第二次买入相当于第一天内买入卖出再买入了。只有这样初始化才能方便后面的推导。 -
遍历顺序:从前往后
-
举例推导
代码
class Solution:
def maxProfit(self, prices: List[int]) -> int:
dp = [[0] * 5 for _ in range(len(prices))]
dp[0][1] = -prices[0]
dp[0][3] = -prices[0]
for i in range(1, len(prices)):
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i])
dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + prices[i])
dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i])
dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i])
return dp[-1][4]
- 时间复杂度:
O(n)
- 空间复杂度:
O(n × 5)
188.买卖股票的最佳时机IV
思路
这题是上一题的超级加倍版本,要求最多可以有k笔交易。
总结地来说,如果最多有可以k笔交易,那么我们需要设2k个状态。参考上一题,最多两笔交易,我们有4个状态(不包括0操作)。
在每天的买入和卖出的状态中,j
为奇数则为买入,j
为偶数则为卖出。
代码
class Solution:
def maxProfit(self, k: int, prices: List[int]) -> int:
dp = [[0] * (2 * k + 1) for _ in range(len(prices))]
for i in range(1, k+1):
# 为买入的状态做初始化
dp[0][2 * i - 1] = -prices[0]
for i in range(1,len(prices)):
for j in range(1, k + 1):
# 奇数买入
dp[i][2*j-1] = max(dp[i-1][2*j-1], dp[i-1][2*j-2] - prices[i])
# 偶数卖出
dp[i][2*j] = max(dp[i-1][2*j], dp[i-1][2*j-1] + prices[i])
return dp[-1][-1]
- 时间复杂度:
O(n * k)
,其中 n 为 prices 的长度 - 空间复杂度:
O(n * k)