Wiggle Subsequence (M)
题目
Given an integer array nums
, return the length of the longest wiggle sequence.
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 fewer than two elements is trivially a wiggle sequence.
- For example,
[1, 7, 4, 9, 2, 5]
is a wiggle sequence because the differences(6, -3, 5, -7, 3)
are alternately positive and negative. - In contrast,
[1, 4, 7, 2, 5]
and[1, 7, 4, 5, 5]
are not wiggle sequences, the first because its first two differences are positive and the second because its last difference is zero.
A subsequence is obtained by deleting some elements (eventually, also zero) from the original sequence, leaving the remaining elements in their original order.
Example 1:
Input: nums = [1,7,4,9,2,5]
Output: 6
Explanation: The entire sequence is a wiggle sequence.
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].
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?
题意
在数组中找到一个子序列,使得子序列中每两个元素的差值一正一负。
思路
比较容易想到的是动态规划。dp[i]表示以nums[i]为结尾的满足条件的子序列的长度,且若最后两个元素之间的差值为负数,dp[i]为负数。对于每一个i,遍历j从0 ~ i-1,找到nums[i]能与dp[j]组成的最大长度的子序列。时间复杂度为(O(N^2))。
(O(N))动态规划:维护两个数组up和down,up[i]表示子数组nums[0-i]中能找到的符合条件的子序列的最大长度,且该子序列的最后一个元素大于倒数第二个元素;down[i]表示子数组nums[0-i]中能找到的符合条件的子序列的最大长度,且该子序列的最后一个元素小于倒数第二个元素。遍历数组,如果当前元素大于前一个,说明可以拓展down[i-1]代表的子序列来得到up[i];如果当前元素小于前一个,说明可以拓展up[i-1]代表的子序列来得到down[i]。为了进一步减小空间复杂度,可以直接用up和down两个整数来代替数组。
代码实现
Java
动态规划 O(N^2)
class Solution {
public int wiggleMaxLength(int[] nums) {
if (nums.length < 2) return nums.length;
int maxLen = 1;
int[] dp = new int[nums.length];
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
int diff = nums[i] - nums[j];
if (diff * dp[j] < 0 && Math.abs(dp[j]) + 1 > Math.abs(dp[i])) {
dp[i] = dp[j] < 0 ? -dp[j] + 1 : -dp[j] - 1;
} else if (dp[j] == 0 && diff != 0 && Math.abs(dp[i]) < 2) {
dp[i] = diff < 0 ? -2 : 2;
}
}
maxLen = Math.max(maxLen, Math.abs(dp[i]));
}
return maxLen;
}
}
动态规划 O(N)
class Solution {
public int wiggleMaxLength(int[] nums) {
if (nums.length < 2) return nums.length;
int up = 1, down = 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 Math.max(up, down);
}
}