[LeetCode]376. 摆动序列(动态规划/贪心)

376. 摆动序列

解法一:动态规划:

​ 找到一个下标元素可能的状态,是上升序列的末尾还是下降序列的末尾。

// 动态规划
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int n = nums.size();
        if (n < 2) return n;
        vector<int> up(n), down(n);
        up[0] = down[0] = 1;
        for (int i = 1; i < n; i++) {
            // 当前元素是一个上升的元素
            if (nums[i] > nums[i - 1]) {
                // 则当前以上升元素结尾的子序列最长可能由,上一个以up结尾的子序列长度和down结尾子序列+1取max
                up[i] = max(up[i - 1], down[i - 1] + 1);
                down[i] = down[i - 1];
            } else if (nums[i] < nums[i - 1]) {
                up[i] = up[i - 1];
                down[i] = max(down[i - 1], up[i - 1] + 1);
            } else {
                up[i] = up[i - 1];
                down[i] = down[i - 1];
            }
        }
        return max(down[n - 1], up[n - 1]);
    }
};


// 降维
class Solution1 {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int n = nums.size();
        if (n < 2) return n;
        int down = 1, up = 1;
        for (int i = 1; i < n; i++) {
            if (nums[i] > nums[i - 1]) {
                up = max(up, down + 1);
            } else {
                down = max(down, up + 1);
            }
        }
        return max(down, up);
    }
};

贪心:比较好想

// 贪心,只关注“峰”和“谷”,峰和谷一定在最长的摆动序列中
class Solution2 {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int n = nums.size();
        if (n < 2) return n;
        int prev_diff = nums[1] - nums[0];
        int res = prev_diff != 0 ? 2 : 1;
        for (int i = 2; i < n; i++) {
            int diff = nums[i] - nums[i - 1];
            // 不是一定要找到峰和谷元素,出现上升或下降趋势,我们就知道一定存在峰或谷,直接可以res++
            if ((diff > 0 && prev_diff <= 0) || diff < 0 && prev_diff >= 0) {
                res++;
                prev_diff = diff;
            }
        }
        return res;
    }
};
posted @ 2020-12-12 11:03  macguz  阅读(220)  评论(0)    收藏  举报