加载中...
376-摆动序列(Wiggle Subsequence)
发表于:2021-12-03 | 分类: 中等
字数统计: 636 | 阅读时长: 3分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/wiggle-subsequence

英文原文

A wiggle sequence is a sequence where the differences between successive numbers strictly alternate between positive and negative. The first difference (if one exists) may be either positive or negative. A sequence with one element and a sequence with two non-equal elements are trivially wiggle sequences.

  • For example, [1, 7, 4, 9, 2, 5] is a wiggle sequence because the differences (6, -3, 5, -7, 3) alternate between positive and negative.
  • In contrast, [1, 4, 7, 2, 5] and [1, 7, 4, 5, 5] are not wiggle sequences. The first is not because its first two differences are positive, and the second is not because its last difference is zero.

A subsequence is obtained by deleting some elements (possibly zero) from the original sequence, leaving the remaining elements in their original order.

Given an integer array nums, return the length of the longest wiggle subsequence of nums.

 

Example 1:

Input: nums = [1,7,4,9,2,5]
Output: 6
Explanation: The entire sequence is a wiggle sequence with differences (6, -3, 5, -7, 3).

Example 2:

Input: nums = [1,17,5,10,13,15,10,5,16,8]
Output: 7
Explanation: There are several subsequences that achieve this length.
One is [1, 17, 10, 13, 10, 16, 8] with differences (16, -7, 3, -3, 6, -8).

Example 3:

Input: nums = [1,2,3,4,5,6,7,8,9]
Output: 2

 

Constraints:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000

 

Follow up: Could you solve this in O(n) time?

中文题目

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

  • 例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。

  • 相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列 最长子序列的长度

 

示例 1:

输入:nums = [1,7,4,9,2,5]
输出:6
解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。

示例 2:

输入:nums = [1,17,5,10,13,15,10,5,16,8]
输出:7
解释:这个序列包含几个长度为 7 摆动序列。
其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。

示例 3:

输入:nums = [1,2,3,4,5,6,7,8,9]
输出:2

 

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000

 

进阶:你能否用 O(n) 时间复杂度完成此题?

通过代码

高赞题解

思路

本题大家都很容易想到用动态规划来求解,求解的过程类似最长上升子序列,不过是需要判断两个序列。大家在实现动态规划的平方复杂度时,就会考虑如何优化到线性复杂度。

假设 up[i] 表示 nums[0:i] 中最后两个数字递增的最长摆动序列长度,down[i] 表示 nums[0:i] 中最后两个数字递减的最长摆动序列长度,只有一个数字时默认为 1

接下来我们进行分类讨论:

  1. nums[i+1] > nums[i]
    • 假设 down[i] 表示的最长摆动序列的最远末尾元素下标正好为 i,遇到新的上升元素后,up[i+1] = down[i] + 1 ,这是因为 up 一定从 down 中产生(初始除外),并且 down[i] 此时最大。
    • 假设 down[i] 表示的最长摆动序列的最远末尾元素下标小于 i,设为 j,那么 nums[j:i] 一定是递增的,因为若完全递减,最远元素下标等于 i,若波动,那么 down[i] > down[j]。由于 nums[j:i] 递增,down[j:i] 一直等于 down[j] ,依然满足 up[i+1] = down[i] + 1
  2. nums[i+1] < nums[i],类似第一种情况
  3. nums[i+1] == nums[i],新的元素不能用于任何序列,保持不变

演示

nums=[1,7,4,9,2,5] 时,演示如下:
image.png
怎么样,是不是清晰易懂呀~

注意到 downup 只和前一个状态有关,所以我们可以优化存储,分别用一个变量即可。

代码

[]
public int wiggleMaxLength(int[] nums) { int down = 1, up = 1; for (int i = 1; i < nums.length; i++) { if (nums[i] > nums[i - 1]) up = down + 1; else if (nums[i] < nums[i - 1]) down = up + 1; } return nums.length == 0 ? 0 : Math.max(down, up); }

统计信息

通过次数 提交次数 AC比率
82725 177332 46.6%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
375-猜数字大小 II(Guess Number Higher or Lower II)
下一篇:
377-组合总和 Ⅳ(Combination Sum IV)
本文目录
本文目录