文章目录
- 摘要
- 描述
- 题解答案
- 题解代码分析
- 代码解析
- 示例测试及结果
- 时间复杂度
- 空间复杂度
- 总结
摘要
今天我们要聊的是 LeetCode 第 376 题 —— 摆动序列。
题目的意思其实很有意思:如果一个序列里的相邻差值能保持正负交替,就叫做“摆动”。比如 [1, 7, 4, 9, 2, 5]
,它就像过山车一样,上下起伏,非常符合“摆动”的定义。
这道题的目标就是:从给定数组中找到最长的摆动子序列长度。
我会带你先理解题意,再分析解法,最后用 Swift 写出可运行的 Demo,并结合实际场景让这个抽象的问题更容易理解。
描述
题目要求我们找到数组中最长的摆动子序列:
- 如果相邻两个数的差严格正负交替,那么就是摆动序列。
- 一个数字或者两个不相等的数字也算摆动序列。
- 允许我们删掉一些数,但不能打乱顺序。
比如:
[1, 7, 4, 9, 2, 5]
→ 差值是(6, -3, 5, -7, 3)
,完全正负交替,长度就是 6。[1, 17, 10, 13, 10, 16, 8]
→ 差值(16, -7, 3, -3, 6, -8)
,长度是 7。[1, 2, 3, 4, 5, 6, 7, 8, 9]
→ 最长只有两个数,因为它一直是递增,没有“起伏”。
题解答案
这道题的本质是一个 动态规划 + 贪心思想 的组合问题。
我们只需要关心当前“趋势”:
- 如果当前差值是正的,就意味着我们找到了一个“上升摆动”。
- 如果当前差值是负的,就意味着我们找到了一个“下降摆动”。
于是,我们可以用两个变量来动态记录:
up[i]
表示以第 i 个元素结尾的最长上升摆动序列长度。down[i]
表示以第 i 个元素结尾的最长下降摆动序列长度。
状态转移关系:
-
如果
nums[i] > nums[i-1]
:up[i] = down[i-1] + 1
-
如果
nums[i] < nums[i-1]
:down[i] = up[i-1] + 1
-
如果相等,啥也不变。
最后结果就是 max(up[n-1], down[n-1])
。
这个逻辑其实就像我们生活中“情绪波动”一样:
- 当你心情一直很嗨(递增),突然遇到挫折(下降),这时候才算一次“摆动”;
- 当你心情很低落(下降),突然遇到好事(上升),又算一次“摆动”。
如果一直高歌猛进或者持续低迷,就没有摆动。
题解代码分析
下面我们用 Swift 来实现:
import Foundationclass Solution {func wiggleMaxLength(_ nums: [Int]) -> Int {if nums.count < 2 { return nums.count }var up = 1var down = 1for i in 1..<nums.count {if nums[i] > nums[i - 1] {up = down + 1} else if nums[i] < nums[i - 1] {down = up + 1}}return max(up, down)}
}
代码解析
-
初始化
如果数组长度小于 2,直接返回数组长度。因为一个数或两个不相等的数就是摆动序列。 -
定义变量
up
和down
初始值都设为 1。代表至少可以形成一个单独的数字序列。 -
遍历数组
- 如果当前数比前一个大,说明找到一个上升趋势,于是
up = down + 1
。 - 如果当前数比前一个小,说明找到一个下降趋势,于是
down = up + 1
。 - 如果相等,不做任何更新。
- 如果当前数比前一个大,说明找到一个上升趋势,于是
-
返回结果
最后返回max(up, down)
,即最长的摆动子序列。
示例测试及结果
我们来跑几个例子验证一下:
let solution = Solution()print(solution.wiggleMaxLength([1, 7, 4, 9, 2, 5]))
// 输出: 6print(solution.wiggleMaxLength([1, 17, 5, 10, 13, 15, 10, 5, 16, 8]))
// 输出: 7print(solution.wiggleMaxLength([1, 2, 3, 4, 5, 6, 7, 8, 9]))
// 输出: 2
输出结果:
6
7
2
结果和题目示例完全一致。
时间复杂度
我们只遍历了一次数组,每个元素只做了常数操作。
因此时间复杂度是 O(n)。
空间复杂度
我们只用了常数个变量 up
和 down
,不需要额外存储数组。
因此空间复杂度是 O(1)。
总结
这道题的关键点在于:
- 不要陷入“暴力枚举所有子序列”的陷阱。那样复杂度太高。
- 只需要用两个变量跟踪“上升”和“下降”的最长长度,就能搞定。
从实际场景来看,它就像分析“股市行情”或“人的情绪波动”:
- 如果股价总是涨(或总是跌),最长的摆动长度就很小。
- 如果股价能反复起伏,摆动序列就会变长。
所以这个算法思路不仅能解决题目,还能帮助我们理解“变化趋势”在数据分析里的意义。