🧠
Brute Force (Pure Recursion)
💡 This approach explores all subsequences to find the longest wiggle subsequence. It is extremely inefficient but helps understand the problem deeply by considering every possibility.
Intuition
Try every subsequence by recursively deciding whether to include or exclude each element, checking if the wiggle property holds.
Algorithm
- Start from the first element and recursively explore subsequences.
- At each step, decide to include the current element if it forms a wiggle with the previous included element.
- Keep track of the last difference sign to ensure alternation.
- Return the maximum length found among all valid subsequences.
💡 The recursion explores all subsequences, which is conceptually simple but computationally expensive.
def wiggleMaxLength(nums):
def dfs(index, prev, diff):
if index == len(nums):
return 0
taken = 0
if diff == 0 or (nums[index] - prev) * diff < 0:
taken = 1 + dfs(index + 1, nums[index], nums[index] - prev)
not_taken = dfs(index + 1, prev, diff)
return max(taken, not_taken)
if not nums:
return 0
return 1 + dfs(1, nums[0], 0)
# Driver code
if __name__ == '__main__':
print(wiggleMaxLength([1,7,4,9,2,5])) # Expected output: 6
Line Notes
def dfs(index, prev, diff):Defines recursive helper to explore subsequences from current index
if index == len(nums):Base case: reached end of array, no more elements to consider
if diff == 0 or (nums[index] - prev) * diff < 0:Check if current difference alternates sign or is first difference
taken = 1 + dfs(index + 1, nums[index], nums[index] - prev)Include current element and recurse
not_taken = dfs(index + 1, prev, diff)Exclude current element and recurse
return max(taken, not_taken)Choose the better option between taking or skipping current element
if not nums:Handle empty input edge case
return 1 + dfs(1, nums[0], 0)Start recursion with first element included and no previous difference
public class Solution {
public int wiggleMaxLength(int[] nums) {
return nums.length == 0 ? 0 : 1 + dfs(nums, 1, nums[0], 0);
}
private int dfs(int[] nums, int index, int prev, int diff) {
if (index == nums.length) return 0;
int taken = 0;
if (diff == 0 || (nums[index] - prev) * diff < 0) {
taken = 1 + dfs(nums, index + 1, nums[index], nums[index] - prev);
}
int notTaken = dfs(nums, index + 1, prev, diff);
return Math.max(taken, notTaken);
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.wiggleMaxLength(new int[]{1,7,4,9,2,5})); // Expected: 6
}
}
Line Notes
public int wiggleMaxLength(int[] nums)Entry point for solution, handles empty array
return nums.length == 0 ? 0 : 1 + dfs(...)Start recursion with first element included
private int dfs(int[] nums, int index, int prev, int diff)Recursive helper exploring subsequences
if (index == nums.length) return 0;Base case: no more elements to process
if (diff == 0 || (nums[index] - prev) * diff < 0)Check if current difference alternates sign
taken = 1 + dfs(...)Include current element and recurse
int notTaken = dfs(...)Exclude current element and recurse
return Math.max(taken, notTaken);Choose best option
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int dfs(const vector<int>& nums, int index, int prev, int diff) {
if (index == nums.size()) return 0;
int taken = 0;
if (diff == 0 || (nums[index] - prev) * diff < 0) {
taken = 1 + dfs(nums, index + 1, nums[index], nums[index] - prev);
}
int notTaken = dfs(nums, index + 1, prev, diff);
return max(taken, notTaken);
}
int wiggleMaxLength(vector<int>& nums) {
if (nums.empty()) return 0;
return 1 + dfs(nums, 1, nums[0], 0);
}
};
int main() {
Solution sol;
vector<int> nums = {1,7,4,9,2,5};
cout << sol.wiggleMaxLength(nums) << endl; // Expected: 6
return 0;
}
Line Notes
int dfs(const vector<int>& nums, int index, int prev, int diff)Recursive helper exploring subsequences
if (index == nums.size()) return 0;Base case: no more elements
if (diff == 0 || (nums[index] - prev) * diff < 0)Check if difference alternates sign
taken = 1 + dfs(...)Include current element and recurse
int notTaken = dfs(...)Exclude current element and recurse
return max(taken, notTaken);Choose the better option
if (nums.empty()) return 0;Handle empty input
return 1 + dfs(nums, 1, nums[0], 0);Start recursion with first element included
function wiggleMaxLength(nums) {
function dfs(index, prev, diff) {
if (index === nums.length) return 0;
let taken = 0;
if (diff === 0 || (nums[index] - prev) * diff < 0) {
taken = 1 + dfs(index + 1, nums[index], nums[index] - prev);
}
let notTaken = dfs(index + 1, prev, diff);
return Math.max(taken, notTaken);
}
if (nums.length === 0) return 0;
return 1 + dfs(1, nums[0], 0);
}
// Test
console.log(wiggleMaxLength([1,7,4,9,2,5])); // Expected: 6
Line Notes
function dfs(index, prev, diff)Recursive helper to explore subsequences
if (index === nums.length) return 0;Base case: no more elements
if (diff === 0 || (nums[index] - prev) * diff < 0)Check if difference alternates sign
taken = 1 + dfs(...)Include current element and recurse
let notTaken = dfs(...)Exclude current element and recurse
return Math.max(taken, notTaken);Choose best option
if (nums.length === 0) return 0;Handle empty input
return 1 + dfs(1, nums[0], 0);Start recursion with first element included
Each element can be included or excluded, leading to exponential subsequences. Recursion stack depth is O(n).
💡 For n=20, this means over a million calls, which is impractical in interviews.
Interview Verdict: TLE
This approach is too slow for large inputs but is useful to understand the problem and motivate better solutions.