Solution: Wiggle Subsequence
Tags: algorithms, javascript, java, python
Published: 2021-03-18 08:48:18

*This is part of a series of Leetcode solution explanations ([index](https://dev.to/seanpgallivan/leetcode-solutions-index-57fl)). If you liked this solution or found it useful,* ***please like*** *this post and/or* ***upvote*** *[my solution post on Leetcode's forums](https://leetcode.com/problems/wiggle-subsequence/discuss/1115231).*

---

#### [Leetcode Problem #376 (*Medium*): Wiggle Subsequence](https://leetcode.com/problems/wiggle-subsequence/)

---

#### ***Description:***

<br />(*Jump to*: [*Solution Idea*](#idea) || *Code*: [*JavaScript*](#javascript-code) | [*Python*](#python-code) | [*Java*](#java-code) | [*C++*](#c-code))

>
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.

---

#### ***Examples:***
>
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.<br>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`

---

#### ***Idea:***

<br />(*Jump to*: [*Problem Description*](#description) || *Code*: [*JavaScript*](#javascript-code) | [*Python*](#python-code) | [*Java*](#java-code) | [*C++*](#c-code))

The key realization here is that any number that lies in the middle of a stretch of the same direction is extraneous, because the more extreme numbers are the better choices to keep, as they allow for a larger likelihood that a subsequent number will be a directional change.

So the simple answer here is to count the inflection points in our input array (**N**) where the direction changes. There are several ways to do this, but in this solution, we can keep a directional flag (**up**) to keep track of the current direction and then increment our answer (**ans**) and invert **up** when a change is found.

One tricky thing lies in setting the initial direction. Per the instructions, the first number can represent any direction, so we'll have to wait until the first time we see a different number to set our direction. We can check this with a simple **while** loop before the main loop.

Once we finish, we can **return ans**.

---

#### ***Implementation:***

All but Javascript will require an additional check before the main loop to account for an input array with all the same number.

---

#### ***Javascript Code:***
<br />(*Jump to*: [*Problem Description*](#description) || [*Solution Idea*](#idea))
```javascript
var wiggleMaxLength = function(N) {
    let len = N.length, i = 1
    while (N[i] === N[i-1]) i++
    let up = N[i-1] > N[i], ans = 1
    for (; i < len; i++)
        if ((up && N[i] < N[i-1]) || (!up && N[i] > N[i-1]))
            up = !up, ans++
    return ans
};
```

---

#### ***Python Code:***
<br />(*Jump to*: [*Problem Description*](#description) || [*Solution Idea*](#idea))
```python
class Solution:
    def wiggleMaxLength(self, N: List[int]) -> int:
        lenN, i = len(N), 1
        while i < lenN and N[i] == N[i-1]: i += 1
        if i == lenN: return 1
        up, ans = N[i-1] > N[i], 1
        while i < lenN:
            if (up and N[i] < N[i-1]) or (not up and N[i] > N[i-1]):
                up = not up
                ans += 1
            i += 1
        return ans
```

---

#### ***Java Code:***
<br />(*Jump to*: [*Problem Description*](#description) || [*Solution Idea*](#idea))
```java
class Solution {
    public int wiggleMaxLength(int[] N) {
        int len = N.length, i = 1, ans = 1;
        while (i < len && N[i] == N[i-1]) i++;
        if (i == len) return 1;
        boolean up = N[i-1] > N[i];
        for (; i < len; i++)
            if ((up && N[i] < N[i-1]) || (!up && N[i] > N[i-1])) {
                up = !up;
                ans++;
            }
        return ans;
    }
}
```

---

#### ***C++ Code:***
<br />(*Jump to*: [*Problem Description*](#description) || [*Solution Idea*](#idea))
```c++
class Solution {
public:
    int wiggleMaxLength(vector<int>& N) {
        int len = N.size(), i = 1, ans = 1;
        while (i < len && N[i] == N[i-1]) i++;
        if (i == len) return 1;
        bool up = N[i-1] > N[i];
        for (; i < len; i++)
            if ((up && N[i] < N[i-1]) || (!up && N[i] > N[i-1]))
                up = !up, ans++;
        return ans;
    }
};
```