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/