746 字
4 分钟
代码随想录算法训练营第三十六天 | 动态规划 Part09

188. 买卖股票的最佳时机 IV#

LeetCode 188. Best Time to Buy and Sell Stock IV

思路:

  • 定义 dp[i][j][0] 表示第 i 天结束后,最多可以进行 j 次交易,不持股 的最大利润;
  • 定义 dp[i][j][1] 表示第 i 天结束后,最多可以进行 j 次交易,持股 的最大利润;
  • 转移方程:
    • dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j][1] + prices[i])
    • dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0] - prices[i])
  • 特殊处理当 k >= n // 2 的情况(退化为无限次交易)
class Solution:
def maxProfit(self, k: int, prices: List[int]) -> int:
n = len(prices)
if n <= 0:
return 0
# 当 k >= n // 2,相当于可以无限次交易
if k >= n // 2:
return sum(max(0, prices[i+1] - prices[i]) for i in range(n - 1))
# 初始化三维 dp 数组: dp[i][j][0/1]
# 第 i 天,最多交易 j 次,0 表示未持股,1 表示持股
dp = [[[0, 0] for _ in range(k + 1)] for _ in range(n)]
# 初始化第 0 天的状态
for i in range(n):
dp[i][0][1] = float('-inf') # 不可能持股
dp[i][0][0] = 0 # 不持股的收益为 0
for i in range(n):
for j in range(k, 0, -1):
if i == 0:
# 第 0 天单独处理
dp[i][j][0] = 0
dp[i][j][1] = -prices[i]
continue
# 不持股:前一天就不持股 or 今天卖出股票
dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i])
# 持股:前一天就持股 or 今天买入(从 j-1 的不持股状态)
dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i])
return dp[n - 1][k][0]

309. 最佳买卖股票时机含冷冻期#

LeetCode 309. Best Time to Buy and Sell Stock with Cooldown

思路:

  • 状态定义:

    • dp[i][0] 表示第 i 天不持股的最大利润;
    • dp[i][1] 表示第 i 天持股的最大利润;
  • 转移方程:

    • dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]):今天卖出或不动;
    • dp[i][1] = max(dp[i-1][1], dp[i-2][0] - prices[i]):今天买入或不动;
  • 注意买入后要冷冻一天,因此买入用 dp[i-2][0]

class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
dp = [[0 for _ in range(2)] for _ in range(n)]
for i in range(n):
if i == 0:
# 第 0 天:未持股为 0,持股为 -prices[0]
dp[i][0] = 0
dp[i][1] = -prices[i]
continue
if i == 1:
# 第 1 天:冷冻期特殊处理
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])
dp[i][1] = max(dp[i - 1][1], -prices[i])
continue
# 第 i 天
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])
dp[i][1] = max(dp[i - 1][1], dp[i - 2][0] - prices[i])
return dp[n - 1][0]

714. 买卖股票的最佳时机含手续费#

LeetCode 714. Best Time to Buy and Sell Stock with Transaction Fee

思路:

  • 状态定义与 309 类似;

  • 每次买入/卖出需要支付手续费 fee

  • 因此在买入时多减一个 fee

    • dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i] - fee)
  • 卖出时不需要再扣 fee(因为已在买入时扣除)

class Solution:
def maxProfit(self, prices: List[int], fee: int) -> int:
n = len(prices)
dp = [[0] * 2 for _ in range(n)]
for i in range(n):
if i == 0:
# 第 0 天
dp[i][0] = 0
dp[i][1] = -prices[i] - fee
continue
# 不持股:昨天不持股 or 昨天持股 + 今天卖出
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])
# 持股:昨天持股 or 昨天不持股 - 今天买入 - 手续费
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i] - fee)
return dp[n - 1][0]
代码随想录算法训练营第三十六天 | 动态规划 Part09
https://fuwari.vercel.app/posts/code_musings_day_thirty-six/
作者
Jarrett
发布于
2025-07-22
许可协议
CC BY-NC-SA 4.0