leetcode 376. 擺動序列(三種解法)

如果連續數字之間的差嚴格地在正數和負數之間交替,則數字序列稱爲擺動序列。第一個差(如果存在的話)可能是正數或負數。少於兩個元素的序列也是擺動序列。

例如, [1,7,4,9,2,5] 是一個擺動序列,因爲差值 (6,-3,5,-7,3) 是正負交替出現的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是擺動序列,第一個序列是因爲它的前兩個差值都是正數,第二個序列是因爲它的最後一個差值爲零。

給定一個整數序列,返回作爲擺動序列的最長子序列的長度。 通過從原始序列中刪除一些(也可以不刪除)元素來獲得子序列,剩下的元素保持其原始順序。

示例 1:

輸入: [1,7,4,9,2,5]
輸出: 6
解釋: 整個序列均爲擺動序列。
示例 2:

輸入: [1,17,5,10,13,15,10,5,16,8]
輸出: 7
解釋: 這個序列包含幾個長度爲 7 擺動序列,其中一個可爲[1,17,10,13,10,16,8]。
示例 3:

輸入: [1,2,3,4,5,6,7,8,9]
輸出: 2

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/wiggle-subsequence
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。


思路分析

思路一:

根據動態規劃的思想,需要找準狀態,可知,每一個數值處於兩種狀態,如3 - 4,此時4處於負值狀態,5 - 4此時,4處於正值狀態,那麼我們需要有兩個變量來存儲。
並且由於題目的要求是求出最長的擺動序列,那麼動態規劃的狀態轉折表達式中設置兩個狀態數組,up[i],down[i]分別表示位置i前面(包括i)最長的擺動序列,即最大值,那麼流思維導圖:
在這裏插入圖片描述
思路二:
在思路一的基礎上,我們可知,既然已知每一個數處於的狀態,如位置i的數,我們已知位置i前面所有的狀態,,那麼我們可以一次性遍歷即可:
在這裏插入圖片描述

思路三:
在思路二的基礎上,將空間縮小,因爲我們發現每次參加運算的變量只有位置i和位置i - 1兩個數,因爲,可以直接用兩個變量代替即可。
在這裏插入圖片描述


代碼解析

思路一:

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int size = nums.size();
        if(size == 0)
            return 0;
        int *up = new int[size + 1];
        int *down = new int[size + 1];
        memset(up,0,sizeof(up));
        memset(down,0,sizeof(down));
        up[0] = 1;
        down[0] = 1;
        for(int i = 1;i < size;++i){
            for(int j = 0;j < i;++j){
                if(nums[i] - nums[j] > 0)
                    up[i] = max(up[i],down[j] + 1);
                else if(nums[i] - nums[j] < 0)
                    down[i] = max(down[i],up[j] + 1);
                else {
                    up[i] = up[i - 1];
                    down[i] = down[i - 1];
                }
            }
        }
        return max(down[size - 1],up[size - 1]);
    }
};

在這裏插入圖片描述

思路二:

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int size = nums.size();
        if(size == 0)
            return 0;
        int *up = new int[size + 1];
        int *down = new int[size + 1];
        memset(up,0,sizeof(up));
        memset(down,0,sizeof(down));
        up[0] = 1;
        down[0] = 1;
        for(int i = 1;i < size;++i){
            if(nums[i] - nums[i - 1] > 0){
                up[i] =down[i - 1] + 1;
                down[i] = down[i - 1];
            }
            else if(nums[i] - nums[i - 1] < 0){
                down[i] =up[i - 1] + 1;
                up[i] = up[i - 1];
            }
            else {
                up[i] = up[i - 1];
                down[i] = down[i - 1];
            }
        }
        return max(down[size - 1],up[size - 1]);
    }
};

在這裏插入圖片描述
並且思路二的優化方案,節省空間:

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

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章