Wiggle Subsequence
Wiggle Subsequence
š§© Problem Statement
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 positive and negative. - In contrast,
[1, 4, 7, 2, 5]and[1, 7, 4, 5, 5]are not wiggle sequences.
Given an integer arraynums, return the length of the longest wiggle subsequence ofnums.
š¹ 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].
š Approaches
1. Greedy (Peaks and Valleys) ($O(N)$)
- Concept: We want to count the number of "turning points" (peaks and valleys) in the sequence.
- Key Insight: If we have a sequence of increasing numbers
[1, 2, 3, 4], the longest wiggle subsequence we can pick is just length 2 (start and end). We can't use the middle numbers. - Algorithm:
- Maintain two counters:
upanddown. up: The length of the longest wiggle subsequence ending with an upward move (positive difference).down: The length of the longest wiggle subsequence ending with a downward move (negative difference).- Iterate through
numsfrom index 1: - If
nums[i] > nums[i-1](Increasing): "Up" state is nowdown + 1. (We extend a valley with a peak). - If
nums[i] < nums[i-1](Decreasing): "Down" state is nowup + 1. (We extend a peak with a valley). - If
nums[i] == nums[i-1]: Do nothing (duplicates don't help wiggle). - Return
max(up, down).
This logic implicitly skips over monotonic segments and only counts the extremes.
ā³ Time & Space Complexity
- Time Complexity: $O(N)$. Single pass.
- Space Complexity: $O(1)$.
š Code Implementations
C++
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
if (nums.empty()) return 0;
int up = 1;
int down = 1;
for (int i = 1; i < nums.size(); i++) {
if (nums[i] > nums[i-1]) {
up = down + 1;
} else if (nums[i] < nums[i-1]) {
down = up + 1;
}
}
return max(up, down);
}
};
Python
from typing import List
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
if not nums:
return 0
up = 1
down = 1
for i in range(1, len(nums)):
if nums[i] > nums[i-1]:
up = down + 1
elif nums[i] < nums[i-1]:
down = up + 1
return max(up, down)
Java
class Solution {
public int wiggleMaxLength(int[] nums) {
if (nums.length == 0) return 0;
int up = 1;
int 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);
}
}
š Real-World Analogy
Stock Market Trends:
Imagine tracking a stock price. You want to buy at every local bottom and sell at every local top to maximize transactions. A steady rise 10 -> 20 -> 30 only counts as one "Buy -> Sell". You need volatility (10 -> 20 -> 15 -> 25) to increase your action count.
šÆ Summary
ā Turning Points: The problem reduces to counting how many times the slope flips direction.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int wiggleMaxLength(vector<int> &nums) {
if (nums.empty())
return 0;
int up = 1;
int down = 1;
for (int i = 1; i < nums.size(); i++) {
if (nums[i] > nums[i - 1]) {
up = down + 1;
} else if (nums[i] < nums[i - 1]) {
down = up + 1;
}
}
return max(up, down);
}
};
int main() {
Solution sol;
vector<int> n1 = {1, 7, 4, 9, 2, 5};
cout << "Test Case 1: " << sol.wiggleMaxLength(n1) << endl; // Expect 6
vector<int> n2 = {1, 17, 5, 10, 13, 15, 10, 5, 16, 8};
cout << "Test Case 2: " << sol.wiggleMaxLength(n2) << endl; // Expect 7
vector<int> n3 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << "Test Case 3: " << sol.wiggleMaxLength(n3) << endl; // Expect 2
return 0;
}