376. Wiggle Subsequence
Problem Description
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 <= 10000 <= nums[i] <= 1000
Solution
Python Solution
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
if len(nums) < 2:
return len(nums)
# Initialize the lengths for sequences ending with up and down differences
up = down = 1
# Iterate through the array starting from index 1
for i in range(1, len(nums)):
if nums[i] > nums[i - 1]:
# Current number is greater than previous
# up can be extended from previous down
up = down + 1
elif nums[i] < nums[i - 1]:
# Current number is smaller than previous
# down can be extended from previous up
down = up + 1
# If numbers are equal, up and down remain unchanged
return max(up, down)
Time Complexity: O(n)
Where n is the length of the input array. We only need to iterate through the array once.
Space Complexity: O(1)
Only uses two variables to track the lengths.
Java Solution
class Solution {
public int wiggleMaxLength(int[] nums) {
if (nums.length < 2) {
return nums.length;
}
// Initialize the lengths for sequences ending with up and down differences
int up = 1;
int down = 1;
// Iterate through the array starting from index 1
for (int i = 1; i < nums.length; i++) {
if (nums[i] > nums[i - 1]) {
// Current number is greater than previous
// up can be extended from previous down
up = down + 1;
} else if (nums[i] < nums[i - 1]) {
// Current number is smaller than previous
// down can be extended from previous up
down = up + 1;
}
// If numbers are equal, up and down remain unchanged
}
return Math.max(up, down);
}
}
Time Complexity: O(n)
Where n is the length of the input array. We only need to iterate through the array once.
Space Complexity: O(1)
Only uses two variables to track the lengths.
C++ Solution
class Solution {
public:
int wiggleMaxLength(vector& nums) {
if (nums.size() < 2) {
return nums.size();
}
// Initialize the lengths for sequences ending with up and down differences
int up = 1;
int down = 1;
// Iterate through the array starting from index 1
for (int i = 1; i < nums.size(); i++) {
if (nums[i] > nums[i - 1]) {
// Current number is greater than previous
// up can be extended from previous down
up = down + 1;
} else if (nums[i] < nums[i - 1]) {
// Current number is smaller than previous
// down can be extended from previous up
down = up + 1;
}
// If numbers are equal, up and down remain unchanged
}
return max(up, down);
}
};
Time Complexity: O(n)
Where n is the length of the input array. We only need to iterate through the array once.
Space Complexity: O(1)
Only uses two variables to track the lengths.
JavaScript Solution
/**
* @param {number[]} nums
* @return {number}
*/
var wiggleMaxLength = function(nums) {
if (nums.length < 2) {
return nums.length;
}
// Initialize the lengths for sequences ending with up and down differences
let up = 1;
let down = 1;
// Iterate through the array starting from index 1
for (let i = 1; i < nums.length; i++) {
if (nums[i] > nums[i - 1]) {
// Current number is greater than previous
// up can be extended from previous down
up = down + 1;
} else if (nums[i] < nums[i - 1]) {
// Current number is smaller than previous
// down can be extended from previous up
down = up + 1;
}
// If numbers are equal, up and down remain unchanged
}
return Math.max(up, down);
};
Time Complexity: O(n)
Where n is the length of the input array. We only need to iterate through the array once.
Space Complexity: O(1)
Only uses two variables to track the lengths.
C# Solution
public class Solution {
public int WiggleMaxLength(int[] nums) {
if (nums.Length < 2) {
return nums.Length;
}
// Initialize the lengths for sequences ending with up and down differences
int up = 1;
int down = 1;
// Iterate through the array starting from index 1
for (int i = 1; i < nums.Length; i++) {
if (nums[i] > nums[i - 1]) {
// Current number is greater than previous
// up can be extended from previous down
up = down + 1;
} else if (nums[i] < nums[i - 1]) {
// Current number is smaller than previous
// down can be extended from previous up
down = up + 1;
}
// If numbers are equal, up and down remain unchanged
}
return Math.Max(up, down);
}
}
Time Complexity: O(n)
Where n is the length of the input array. We only need to iterate through the array once.
Space Complexity: O(1)
Only uses two variables to track the lengths.
Approach Explanation
The solution uses dynamic programming with space optimization to find the longest wiggle subsequence:
- Key Insights:
- Track two possible states
- Only need previous state
- Alternating pattern
- Greedy approach works
- Algorithm Steps:
- Initialize up and down lengths
- Process array sequentially
- Update based on differences
- Return maximum length
Implementation Details:
- Handle base cases
- Track two states efficiently
- Compare adjacent elements
- Maintain optimal substructure
Optimization Insights:
- Space optimization
- Single pass solution
- No need for extra storage
- Constant space complexity
Edge Cases:
- Empty array
- Single element
- Equal adjacent elements
- Monotonic sequence