LeetCode 188困难动态规划
买卖股票的最佳时机 IV 图解题解
这道题到底在问什么
给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。 注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- k,prices
- 2,[2,4,1]
- 输出
- 2
先想最直接的笨办法
DP 表跟着代码走:推进语句是:return sell[k]。处理过的部分不再重新枚举。(动画第 10 步)
最优解:一步一步想明白
- 3下面 9 步动画会按主解代码推进,而不是泛泛讲题型。
- 4先读清 买卖股票的最佳时机 IV 的输入输出DP 表跟着代码走:先把示例输入映射到代码参数:def maxProfit(self, k, prices):。
- 5n = len(prices);ans = 0DP 表跟着代码走:开局只立住必要变量:n = len(prices);ans = 0。
- 6for i in range(1, n):DP 表跟着代码走:主流程从这里开始:for i in range(1, n):。
- 7if prices[i] > prices[i - 1]:DP 表跟着代码走:题目条件落到这一行:if prices[i] > prices[i - 1]:。
- 8ans += prices[i] - prices[i - 1]DP 表跟着代码走:对应代码:ans += prices[i] - prices[i - 1]。这一行决定当前轮对答案有什么贡献。
- 9k>=n//2 时转无限交易DP 表跟着代码走:边界跟着代码看:return ans。
- 10return sell[k]DP 表跟着代码走:推进语句是:return sell[k]。处理过的部分不再重新枚举。
- 11return sell[k]DP 表跟着代码走:到这里,k 已经能表达题目要求。
- 12return:return sell[k]DP 表跟着代码走:最后检查返回形态:返回值、原地修改或设计类状态,要和 LeetCode 判题方式一致。
- 15记住这题的代码骨架:题意约束先落到状态变量,再用循环或递归维护它。
⚠️ 容易写错的地方
✗ 错:k 很大仍跑 O(kn)
✓ 对:k>=n//2 时转无限交易
交易次数不再是限制
✗ 错:状态更新方向混乱
✓ 对:t 从 1 到 k 更新 buy/sell
sell[t] 依赖 buy[t]
完整代码(Python)
Python
class Solution:
def maxProfit(self, k, prices):
n = len(prices)
if not prices or k == 0:
return 0
if k >= n // 2:
ans = 0
for i in range(1, n):
if prices[i] > prices[i - 1]:
ans += prices[i] - prices[i - 1]
return ans
buy = [-10**18] * (k + 1)
sell = [0] * (k + 1)
for price in prices:
for t in range(1, k + 1):
buy[t] = max(buy[t], sell[t - 1] - price)
sell[t] = max(sell[t], buy[t] + price)
return sell[k]复杂度
时间复杂度
O(kn)
每个价格更新 k 个状态
空间复杂度
O(k)
滚动状态
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 买卖股票的最佳时机 IV 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
这道题为什么用「动态规划」,换最直接的暴力解会差在哪?+
动态规划抓住了本题的结构特征,把暴力解里重复的工作省掉;暴力解通常要多嵌套一层枚举,数据一大就超时。具体对比见上文「暴力解及其卡点」与「最优解逐步推演」两节。
时间复杂度为什么是 undefined?怎么推出来的?+
按上文复杂度小节的推导,时间复杂度为 undefined。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。