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.
[1, 7, 4, 9, 2, 5]
is a wiggle sequence because the differences (6, -3, 5, -7, 3)
alternate between positive and negative.[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?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The wiggle subsequence problem asks us to find the longest sequence within a given sequence where the differences between consecutive numbers alternate between positive and negative. The brute force approach involves checking every possible subsequence to see if it wiggles and then picking the longest one.
Here's how the algorithm would work step-by-step:
def wiggle_subsequence_brute_force(numbers):
maximum_length = 0
def is_wiggle(subsequence):
if len(subsequence) < 2:
return True
sign = 0
for i in range(1, len(subsequence)):
difference = subsequence[i] - subsequence[i - 1]
if difference == 0:
return False
current_sign = 1 if difference > 0 else -1
if sign == 0:
sign = current_sign
elif sign == current_sign:
return False
else:
sign = current_sign
return True
def find_subsequences(index, current_subsequence):
nonlocal maximum_length
# If we reach the end of the original sequence, check the subsequence.
if index == len(numbers):
if is_wiggle(current_subsequence):
maximum_length = max(maximum_length, len(current_subsequence))
return
# Explore the possibility of including the current number in the subsequence.
find_subsequences(index + 1, current_subsequence + [numbers[index]])
# Explore the possibility of excluding the current number.
find_subsequences(index + 1, current_subsequence)
# Start the recursive search for wiggle subsequences.
find_subsequences(0, [])
return maximum_length
The goal is to find the longest sequence where the differences between adjacent numbers alternate between positive and negative. We can find this sequence by keeping track of the last positive and negative 'peaks' we've seen and extending the sequence whenever we find a number that forms a new peak.
Here's how the algorithm would work step-by-step:
def wiggle_subsequence(numbers):
if not numbers:
return 0
sequence_length = 1
up_peak = numbers[0]
down_peak = numbers[0]
for index in range(1, len(numbers)):
current_number = numbers[index]
# Extend increasing seq.
if current_number > up_peak:
sequence_length += 1
down_peak = current_number
# Extend decreasing seq.
elif current_number < down_peak:
sequence_length += 1
up_peak = current_number
return sequence_length
Case | How to Handle |
---|---|
Empty or null input array | Return 0, as an empty array has no wiggle subsequence. |
Array with one element | Return 1, as a single element forms a wiggle subsequence of length 1. |
Array with two identical elements | Return 1, as two identical elements do not form a wiggle subsequence. |
Array with two distinct elements | Return 2, as any two distinct elements form a wiggle subsequence. |
Array with all identical elements | Return 1, as all identical elements do not form any wiggle. |
Array with strictly increasing or decreasing elements | The algorithm should correctly identify the first increase or decrease and count the elements accordingly. |
Array with alternating positive and negative differences | The algorithm should correctly count each alternating change as part of the wiggle subsequence. |
Large input array with potential integer overflow in difference calculation | Use a data type that can accommodate larger differences (e.g., long) if necessary. |