LeetCode 122中等贪心
买卖股票 II 图解题解
这道题到底在问什么
可以多次买入卖出(手里最多只持一股),求能拿到的最大总利润。
- prices
- [7, 1, 5, 3, 6, 4]
- 输出
- 7
先想最直接的笨办法
最直接的念头是「找一个谷底买进、找一个峰顶卖出」。但能交易很多次,到底切成几段、每段谷峰在哪,枚举起来又乱又慢,而且根本没必要知道具体的买卖点。(动画第 3 步)
最优解:一步一步想明白
- 3最直接的念头是「找一个谷底买进、找一个峰顶卖出」。但能交易很多次,到底切成几段、每段谷峰在哪,枚举起来又乱又慢,而且根本没必要知道具体的买卖点。
- 4换个角度:把利润拆到每一天。今天比昨天涨,就把这点差价收进口袋(相当于昨天买、今天卖);今天比昨天跌,就空仓什么都不做(加 0)。为什么成立:一段连续上涨 1→5 的总收益 4,正好等于它每天小涨之和;所以「把所有正的日差累加」和「整段买卖」收益完全相等,而且不限次数让我们可以自由分段——逐日贪心就是全局最优。
- 5profit = 0利润 profit 从 0 起。第 1 天(价 7)没有前一天可比,cur 先停在这里,真正的累加从第 2 天开始。
- 6diff = 1 − 7 = −6走到第 2 天(价 1),先算今天减昨天:1 − 7 = −6,是负的。
- 7profit += 0 = 0日差是负的,这天不操作(空仓),profit 加 0、保持 0。这就是负例:下跌日一律跳过,灰掉表示没吃进。
- 8diff = 5 − 1 = +4走到第 3 天(价 5),算差:5 − 1 = +4,第一次出现正的涨幅。
- 9profit += 4 = 4日差为正,把这 4 块吃进口袋:profit 累计到 4。绿色标出的 1 和 5 就是这一段「昨天买、今天卖」赚到的钱。
- 10diff = 3 − 5 = −2走到第 4 天(价 3),算差:3 − 5 = −2,又是负的。
- 11profit += 0 = 4下跌日再次跳过,profit 不动,仍是 4。注意这里没有去「找谷底找峰顶」——只看相邻两天的正负就够了。
- 12diff = 6 − 3 = +3走到第 5 天(价 6),算差:6 − 3 = +3,又一段上涨。
- 13profit += 3 = 7正差再吃下 3 块:profit 从 4 累到 7。绿色的 3 和 6 是这第二段赚到的钱。
- 14profit += 0 = 7最后一天 6 → 4 又是跌,跳过。全程只把两段正涨幅累加:4 + 3 = 7,就是答案。
- 17一段连续上涨(如 1→5)拆成每天的差,求和不变;下跌日加 0 不亏。所以「每个正的日差都拿」就等于全局最优——这就是贪心在这题成立的根本原因。
⚠️ 容易写错的地方
✗ 错:费劲去找全局最低点买、最高点卖
✓ 对:只累加每段正的日差 max(0, 今−昨)
不限次数时根本不用知道具体谷峰,分段累加正涨幅就是最优,找谷峰反而又慢又容易切错段
✗ 错:把这套累加直接用在「只能交易一次」的 LC121
✓ 对:一次交易要维护历史最低价 minPrice 求最大单段差
次数受限时利润不可分段独立累加,简单加正差会偏大
✗ 错:for i in range(len(prices)) 从 0 开始
✓ 对:for i in range(1, len(prices))
第 1 天没有「昨天」,从 0 起会越界访问 prices[-1]
完整代码(Python)
Python
class Solution:
def maxProfit(self, prices):
ans = 0
for i in range(1, len(prices)):
if prices[i] > prices[i - 1]:
ans += prices[i] - prices[i - 1]
return ans套路模板 · 累加正向增量(背下来)
# 「操作次数不限、收益可分段独立」的贪心都套
total = 0
for i in range(1, n):
gain = 收益(i - 1, i)
if gain > 0: total += gain # 只累加正收益
return total复杂度
时间复杂度
O(n)
只从第 2 天到最后扫一遍,每天做一次比较
空间复杂度
O(1)
只用 profit 一个变量,不开任何数组
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 买卖股票 II 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
这道题为什么用「贪心」,换最直接的暴力解会差在哪?+
贪心抓住了本题的结构特征,把暴力解里重复的工作省掉;暴力解通常要多嵌套一层枚举,数据一大就超时。具体对比见上文「暴力解及其卡点」与「最优解逐步推演」两节。
时间复杂度为什么是 undefined?怎么推出来的?+
按上文复杂度小节的推导,时间复杂度为 undefined。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。