最长摆动子序列
字数 1230 2025-11-03 08:34:53

最长摆动子序列

题目描述:
给定一个整数数组 nums,返回 nums 中作为摆动序列的最长子序列的长度。摆动序列是指连续数字之间的差严格地在正数和负数之间交替。第一个差值(如果存在的话)可能是正数或负数。如果少于两个元素,则序列是摆动序列。例如,[1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 正负交替。

解题过程:

  1. 问题分析:
  • 我们需要找到最长的子序列(不要求连续),使得这个子序列中相邻元素的差值正负交替
  • 关键观察:对于任意位置 i,它可能处于两种状态:
    • up[i]:以 i 结尾且最后一步是上升(nums[i] > 前一个元素)的最长摆动序列长度
    • down[i]:以 i 结尾且最后一步是下降(nums[i] < 前一个元素)的最长摆动序列长度
  1. 状态定义:
  • up[i]:以第 i 个元素结尾,且最后一步是上升的最长摆动子序列长度
  • down[i]:以第 i 个元素结尾,且最后一步是下降的最长摆动子序列长度
  1. 状态转移方程:
    对于每个位置 i,我们需要考虑所有 j < i 的情况:
  • 如果 nums[i] > nums[j],那么 i 可以接在 j 的下降序列后面形成上升
    up[i] = max(up[i], down[j] + 1)
  • 如果 nums[i] < nums[j],那么 i 可以接在 j 的上升序列后面形成下降
    down[i] = max(down[i], up[j] + 1)
  1. 初始化:
  • 每个位置本身就是一个长度为1的摆动序列
  • up[0] = 1, down[0] = 1
  1. 优化实现:
    实际上我们可以用 O(n) 时间复杂度的贪心解法:
  • 维护两个变量 up 和 down,分别表示当前最长的上升摆动序列和下降摆动序列长度
  • 遍历数组,当遇到上升时,up = down + 1
  • 当遇到下降时,down = up + 1
  1. 具体步骤:
  • 如果 nums.length < 2,直接返回数组长度
  • 初始化 up = 1, down = 1
  • 从 i = 1 开始遍历数组:
    • 如果 nums[i] > nums[i-1]:up = down + 1
    • 如果 nums[i] < nums[i-1]:down = up + 1
  • 返回 max(up, down)
  1. 示例验证:
    对于 nums = [1,7,4,9,2,5]:
  • i=1: 1→7(上升),up = 1+1=2, down=1
  • i=2: 7→4(下降),down = 2+1=3, up=2
  • i=3: 4→9(上升),up = 3+1=4, down=3
  • i=4: 9→2(下降),down = 4+1=5, up=4
  • i=5: 2→5(上升),up = 5+1=6, down=5
    最终结果为6,与题目示例一致。

这种解法的时间复杂度是 O(n),空间复杂度是 O(1),是最优解法。

最长摆动子序列 题目描述: 给定一个整数数组 nums,返回 nums 中作为摆动序列的最长子序列的长度。摆动序列是指连续数字之间的差严格地在正数和负数之间交替。第一个差值(如果存在的话)可能是正数或负数。如果少于两个元素,则序列是摆动序列。例如,[ 1,7,4,9,2,5 ] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 正负交替。 解题过程: 问题分析: 我们需要找到最长的子序列(不要求连续),使得这个子序列中相邻元素的差值正负交替 关键观察:对于任意位置 i,它可能处于两种状态: up[ i]:以 i 结尾且最后一步是上升(nums[ i ] > 前一个元素)的最长摆动序列长度 down[ i]:以 i 结尾且最后一步是下降(nums[ i] < 前一个元素)的最长摆动序列长度 状态定义: up[ i ]:以第 i 个元素结尾,且最后一步是上升的最长摆动子序列长度 down[ i ]:以第 i 个元素结尾,且最后一步是下降的最长摆动子序列长度 状态转移方程: 对于每个位置 i,我们需要考虑所有 j < i 的情况: 如果 nums[ i] > nums[ j ],那么 i 可以接在 j 的下降序列后面形成上升 up[ i] = max(up[ i], down[ j ] + 1) 如果 nums[ i] < nums[ j ],那么 i 可以接在 j 的上升序列后面形成下降 down[ i] = max(down[ i], up[ j ] + 1) 初始化: 每个位置本身就是一个长度为1的摆动序列 up[ 0] = 1, down[ 0 ] = 1 优化实现: 实际上我们可以用 O(n) 时间复杂度的贪心解法: 维护两个变量 up 和 down,分别表示当前最长的上升摆动序列和下降摆动序列长度 遍历数组,当遇到上升时,up = down + 1 当遇到下降时,down = up + 1 具体步骤: 如果 nums.length < 2,直接返回数组长度 初始化 up = 1, down = 1 从 i = 1 开始遍历数组: 如果 nums[ i] > nums[ i-1 ]:up = down + 1 如果 nums[ i] < nums[ i-1 ]:down = up + 1 返回 max(up, down) 示例验证: 对于 nums = [ 1,7,4,9,2,5 ]: i=1: 1→7(上升),up = 1+1=2, down=1 i=2: 7→4(下降),down = 2+1=3, up=2 i=3: 4→9(上升),up = 3+1=4, down=3 i=4: 9→2(下降),down = 4+1=5, up=4 i=5: 2→5(上升),up = 5+1=6, down=5 最终结果为6,与题目示例一致。 这种解法的时间复杂度是 O(n),空间复杂度是 O(1),是最优解法。