题目来源:LeetCode 376. 摆动序列
问题抽象: 给定一个整数数组 nums,需计算其 最长摆动子序列 的长度,满足以下核心需求:
-
摆动序列定义:
- 子序列中相邻元素的差值 严格交替变化(正→负→正 或 负→正→负);
- 若差值序列为
[d1, d2, d3, ...],则对所有i有d_i × d_{i+1} < 0(符号相反); - 单元素序列 视为有效摆动序列(长度
1); - 两元素不等序列 自动满足摆动条件(长度
2)。
-
优化目标:
- 子序列 不要求连续(可从原序列中删除部分元素);
- 在所有摆动子序列中,选择 元素数量最多 的子集长度;
- 利用 贪心策略:仅记录序列的波峰和波谷位置(忽略单调区间)。
-
边界处理:
- 空数组:返回
0; - 全等数组:如
[1,1,1]→ 最长摆动序列长度1(单元素); - 头尾处理:序列起始和结束元素无条件计入;
- 平坡处理:连续相等值(如
[1,2,2,3])中仅第一个2可能参与摆动。
- 空数组:返回
-
特殊案例:
[1,7,4,9,2,5]→ 差值[+6,-3,+5,-7,+3]符号交替 → 长度6;[1,17,5,10,13,15,10,5,16,8]→ 最长摆动子序列[1,17,5,15,5,16,8]→ 长度7;[1,2,3,4,5,6,7,8,9]→ 最长摆动序列为任意两个不等元素(如[1,2])→ 长度2。
-
计算约束:
- 时间复杂度 O(n):单次遍历数组,比较相邻元素差值符号;
- 空间复杂度 O(1):仅存储当前符号状态和计数器;
- 输入规模:数组长度
≤ 1000。
输入:整数数组 nums(0 ≤ length ≤ 1000,0 ≤ nums[i] ≤ 1000)
输出:最长摆动子序列长度(整数)。
解题思路
核心目标:找到最长摆动子序列的长度(相邻元素差正负交替)。
贪心策略:通过一次遍历统计波峰和波谷的数量。
关键观察:
- 当序列上升时,摆动序列长度 = 上一次下降的长度 + 1
- 当序列下降时,摆动序列长度 = 上一次上升的长度 + 1
- 相等元素不改变摆动状态
步骤:
- 数组长度 < 2 时,直接返回长度
- 初始化
up和down为 1(表示以升序/降序结尾的最长摆动序列长度) - 遍历数组:
- 当前元素 > 前一个元素:更新
up = down + 1 - 当前元素 < 前一个元素:更新
down = up + 1 - 相等时跳过(不更新状态)
- 当前元素 > 前一个元素:更新
- 返回
max(up, down)
复杂度:时间:O(n),仅遍历一次数组。空间:O(1),仅用两个变量。
代码实现(Java版)🔥点击下载源码
class Solution {
public int wiggleMaxLength(int[] nums) {
int n = nums.length;
// 处理长度小于2的情况
if (n < 2) {
return n;
}
// 初始化上升和下降序列长度
int up = 1; // 以升序结尾的摆动序列长度
int down = 1; // 以降序结尾的摆动序列长度
for (int i = 1; i < n; i++) {
if (nums[i] > nums[i - 1]) {
// 遇到上升:更新up = 前一个下降序列长度 + 1
up = down + 1;
} else if (nums[i] < nums[i - 1]) {
// 遇到下降:更新down = 前一个上升序列长度 + 1
down = up + 1;
}
// 相等时跳过,保持原有状态
}
// 返回最大值(最终序列可能以升序或降序结尾)
return Math.max(up, down);
}
}
代码说明
-
初始化处理:
- 数组长度小于2时,直接返回长度(单元素视为摆动序列)
-
状态变量:
up:记录以升序结尾的最长摆动序列长度(初始值1)down:记录以降序结尾的最长摆动序列长度(初始值1)
-
遍历逻辑:
- 上升趋势 (
nums[i] > nums[i-1]):
当前上升序列长度 = 前一个下降序列长度 + 1 (up = down + 1) - 下降趋势 (
nums[i] < nums[i-1]):
当前下降序列长度 = 前一个上升序列长度 + 1 (down = up + 1) - 相等元素:跳过不更新(不影响摆动状态)
- 上升趋势 (
-
返回值:
- 取
up和down的最大值(最长摆动序列可能以升序或降序结尾)
- 取
示例验证:
输入:[1,7,4,9,2,5]
1→7(升)→up=27→4(降)→down=34→9(升)→up=49→2(降)→down=52→5(升)→up=6
输出:6(符合最长摆动序列长度)
提交详情(执行用时、内存消耗)

971

被折叠的 条评论
为什么被折叠?



