LeetCode 376. Wiggle Subsequence(動態規劃)

題目

給出一個整數序列,求擺動子序列,即子序列相鄰兩位之間的差值正負交替出現的,即序列中相鄰兩個數一大一小交替出現。

Examples:
Input: [1,7,4,9,2,5]
Output: 6
The entire sequence is a wiggle sequence.

Input: [1,17,5,10,13,15,10,5,16,8]
Output: 7
There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].

Input: [1,2,3,4,5,6,7,8,9]
Output: 2

思路

和之前動態規劃做的Best Time to Buy and Sell Stock with Transaction Fee思路一模一樣,這裏再簡單說一下好了。

滿足題意的序列最後兩個數的差值要麼是正數,要麼是負數,因此可以用兩個數組記錄兩種信息,然後交替更新到數組最後一位即可。

定義狀態

    pos[i]: 從nums[0]到nums[i]範圍內符合條件的最長子序列長度,而且最後一個差值是正數
    neg[i]: 從nums[0]到nums[i]範圍內符合條件的最長子序列長度,而且最後一個差值是負數
    額外需要pos_end,neg_end記錄兩個序列的最後一位數字
    最終結果爲 max(pos[n - 1], neg[n - 1])

狀態轉移

這裏寫圖片描述
可見每個狀態都由之前的兩個狀態轉移過來

更新pos[]
①當nums[i] - pos_end > 0時,nums[i]不能直接加到pos序列最後否則連續兩個差值都是正值就違反規定了,但是由貪心策略,此時用nums[i]替換掉pos_end會使得以後尋找下一個數更有利,因爲pos_end越大的話,下一個滿足序列條件的數的範圍也越大(下一個滿足條件的數一定小於pos_end),因此 pos_end = nums[i] , pos[i] = pos[i - 1]

②當nums[i] - neg_end > 0時,pos_end = nums[i],pos[i] = neg[i - 1] + 1

則 pos[i] = max(pos[i - 1],neg[i - 1] + 1)

類似的更新neg[]
③當nums[i] - pos_end < 0時,neg_end = nums[i],neg[i] = pos[i - 1] + 1

④當nums[i] - neg_end < 0時,neg_end = nums[i],neg[i] = neg[i - 1]

則 neg[i] = max(neg[i - 1],pos[i - 1] + 1)

注意:當nums[i] - pos_end == 0時,pos序列的長度和最後一個數都不變,類似的當nums[i] - neg_end == 0時也一樣,這裏的賦值問題有點坑,直接看代碼就清楚了

代碼

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int n = nums.size();
        if (n <= 1) return n;

        //pos[i]: 從nums[0]到nums[i]範圍內符合條件的最長子序列長度,而且最後一個差值是正數
        //neg[i]: 從nums[0]到nums[i]範圍內符合條件的最長子序列長度,而且最後一個差值是負數
        vector<int> pos(n);
        vector<int> neg(n);
        int pos_end = nums[0], neg_end = nums[0];
        pos[0] = neg[0] = 1;


        for (int i = 1; i < n; i++) {
            // pos數組期待下一個差值是負值,neg期待下一個差值是正值
            int expect_neg_diff = nums[i] - pos_end;
            int expect_pos_diff = nums[i] - neg_end;

            int lenx, leny;

            // 更新pos[i],
            // 給lenx和leny初始化長度爲pos[i - 1],
            // 既滿足nums[i] - pos_end == 0時的情況,
            // 也能避免當下面兩個條件都不滿足時出現lenx和leny爲亂值。
            lenx = leny = pos[i - 1];
            if (expect_neg_diff > 0) {
                pos_end = nums[i];
                lenx = pos[i - 1];
            }
            if (expect_pos_diff > 0) {
                pos_end = nums[i];
                leny = neg[i - 1] + 1;
            }
            pos[i] = max(lenx, leny);

            // 更新neg[i],初始化lenx和leny的理由同上
            lenx = leny = neg[i - 1];
            if (expect_pos_diff < 0) {
                neg_end = nums[i];
                lenx = neg[i - 1];
            }
            if (expect_neg_diff < 0) {
                neg_end = nums[i];
                leny = pos[i - 1] + 1;
            }
            neg[i] = max(lenx, leny);
        }


        return max(pos[n - 1], neg[n - 1]);
    }
};
發佈了58 篇原創文章 · 獲贊 11 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章