图解题库 / 贪心

376. 摆动序列

中等 含交互动画

学完这道你应该能: 说清它为什么用「贪心」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

相邻差值正负交替的序列叫摆动序列。求最长摆动子序列长度。

nums = [1, 7, 4, 9, 2, 5]
输出 = 6 (本身就是摆动的)

思路解析

把每个子序列都挑出来、逐一检查是不是一上一下交替,共 2ⁿ 个,指数级。但其实根本不用枚举——最长摆动子序列的长度,就等于原序列里「方向转折」的次数 + 1,一遍扫描数转折就行。

up 表示目前以「上升」结尾的最长摆动长度,down 表示以「下降」结尾的。上升时 up = down + 1,下降时 down = up + 1。答案取两者最大。

起点:从第一个数开始,up 和 down 都是 1。

i=1 · 7>1 上升:7 比前一个 1 大,是上升。up = down + 1 = 2。

i=2 · 4<7 下降:4 比 7 小,是下降。down = up + 1 = 3。

i=3 · 9>4 上升:9 比 4 大,上升。up = down + 1 = 4。

i=4 · 2<9 下降:2 比 9 小,下降。down = up + 1 = 5。

i=5 · 5>2 上升:5 比 2 大,上升。up = down + 1 = 6。

答案:答案 = max(up, down) = 6。(如果相邻两个数相等,up/down 都不变,自动跳过)

摆动序列的长度 = 转折点个数 + 1。把「方向」当状态来维护,这是贪心/状态机的常见套路。

参考代码(Python)

Python
1if len(nums) < 2: return len(nums)
2up = down = 1
3for i in range(1, len(nums)):
4    if nums[i] > nums[i-1]: up = down + 1     # 上升
5    elif nums[i] < nums[i-1]: down = up + 1   # 下降
6    # 相等则都不变
7return max(up, down)

复杂度分析

  • 时间复杂度:O(n) —— 一遍扫描
  • 空间复杂度:O(1) —— 两个变量

套路模板

记住骨架:两个状态此消彼长、只在方向改变时 +1。买卖股票II「只在上涨段累加」也是这种一遍状态贪心。

Python
1# 把「方向 / 状态」当变量,一遍扫描交替更新
2up = down = 1
3for i in range(1, n):
4    if nums[i] > nums[i-1]: up = down + 1   # 升:接在降后面
5    elif nums[i] < nums[i-1]: down = up + 1 # 降:接在升后面
6    # 相等:两者都不动
7return max(up, down)

易错点

  • 相等时也更新 up/down → ✅ 相等(==)时两者都不变(相等不构成上升或下降)
  • 长度 <2 不特判 → ✅ 先处理 len<2 直接返回长度(单元素也是合法摆动序列)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →875. 爱吃香蕉的珂珂 ← 返回题库