最长摆动子序列

int wiggleMaxLength(vector<int>& nums) {
    // 贪心法,摆动发生时增长子序列
    if (nums.empty()) return 0;
    int ans = 1;
    int prevDiff = 0;
    for (int i = 1; i < nums.size(); i++) {
        int diff = nums[i] - nums[i-1];
        if ((diff > 0 && prevDiff <= 0) || (diff < 0 && prevDiff >= 0)) {
            ans++;
            prevDiff = diff;
        }
    }
    return ans;
}

用动态规划麻烦些。O(n^2)的dp类似最长递增子序列。这里讨论O(n)的dp思路。

用up[i]表示子问题nums[0..i]、且最后上升的、最长摇摆子序列长;down[i]表示...且最后下降的...长。

int wiggleMaxLength(vector<int>& nums) {
    if (nums.empty()) return 0;
    const int N = nums.size();
    vector<int> up(N, 0), down(N, 0);
    up[0] = down[0] = 1;
    for (int i = 1; i < N; i++) {
        if (nums[i] > nums[i-1]) {
            // 设down[i-1]对应子序列的最后数是last,last可以是nums[0..i-1]间的数
            //  若last <= nums[i-1],nums[i] > nums[i-1] >= last,可扩展down[i-1]
            //  若last > nums[i-1],可用nums[i-1]替代last,这样nums[i] > 新last,可扩展down[i-1]
            // 所以与last大小无关,都可扩展down[i-1]
            up[i] = down[i-1] + 1;
            // 对down[i]无影响
            down[i] = down[i-1];
        } else if (nums[i] < nums[i-1]) {
            // 同理
            down[i] = up[i-1] + 1;
            up[i] = up[i-1];
        } else {
            // 不能比i-1的情况做得更好
            down[i] = down[i-1];
            up[i] = up[i-1];
        }
    }
    return max(up[N-1], down[N-1]);
}

空间优化:因为第i项只依赖于第i-1项,可将两数组优化成两变量up和down。

int wiggleMaxLength(vector<int>& nums) {
    if (nums.empty()) return 0;
    int up = 1, 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 maxTurbulenceSize(vector<int>& A) {
    if (A.empty()) return 0;

    int len = 1, ans = 1;
    int prevDiff = 0;
    for (int i = 1; i < A.size(); i++) {
        int diff = A[i] - A[i-1];
        if ((diff > 0 && prevDiff <= 0) || (diff < 0 && prevDiff >= 0)) {
            len++;
        } else {
            len = diff == 0 ? 1 : 2;
        }
        ans = max(ans, len);
        prevDiff = diff;
    }
    return ans;
}

动态规划

int maxTurbulenceSize(vector<int>& A) {
    if (A.empty()) return 0;
    int up = 1, down = 1, ans = 1;
    for (int i = 1; i < A.size(); i++) {
        if (A[i] > A[i-1]) {
            up = down + 1;
            down = 1;
        } else if (A[i] < A[i-1]) {
            down = up + 1;
            up = 1;
        } else {
            up = down = 1;
        }
        ans = max({ans, up, down});
    }
    return ans;
}

摆动排序见笔记