力扣-376. 擺動序列

DawnTraveler發表於2024-06-26

1.題目介紹

題目地址(376. 擺動序列 - 力扣(LeetCode))

https://leetcode.cn/problems/wiggle-subsequence/

題目描述

如果連續數字之間的差嚴格地在正數和負數之間交替,則數字序列稱為 擺動序列 。第一個差(如果存在的話)可能是正數或負數。僅有一個元素或者含兩個不等元素的序列也視作擺動序列。

  • 例如, [1, 7, 4, 9, 2, 5] 是一個 擺動序列 ,因為差值 (6, -3, 5, -7, 3) 是正負交替出現的。

  • 相反,[1, 4, 7, 2, 5][1, 7, 4, 5, 5] 不是擺動序列,第一個序列是因為它的前兩個差值都是正數,第二個序列是因為它的最後一個差值為零。

子序列 可以透過從原始序列中刪除一些(也可以不刪除)元素來獲得,剩下的元素保持其原始順序。

給你一個整數陣列 nums ,返回 nums 中作為 擺動序列 最長子序列的長度

示例 1:

輸入:nums = [1,7,4,9,2,5]
輸出:6
解釋:整個序列均為擺動序列,各元素之間的差值為 (6, -3, 5, -7, 3) 。

示例 2:

輸入:nums = [1,17,5,10,13,15,10,5,16,8]
輸出:7
解釋:這個序列包含幾個長度為 7 擺動序列。
其中一個是 [1, 17, 10, 13, 10, 16, 8] ,各元素之間的差值為 (16, -7, 3, -3, 6, -8) 。

示例 3:

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

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000

進階:你能否用 O(n) 時間複雜度完成此題?

2.題解

2.1 動態規劃

思路

這裡我們使用動態規劃,主要明白子序列可能所處的幾種狀態,和它的狀態轉移方程:
1.上升序列up[i], 表示取範圍在[0,i]的上升子序列的最大元素個數
2.下降序列down[i],表示取範圍在[0,i]的下降子序列的最大元素個數

狀態轉移方程:
我們先來討論上升序列情況,由於當前元素nums[i]和nums[i-1]的大小關係,會影響到序列子元素的選擇,所以我們分情況來討論:
1.nums[i] > nums[i-1]
這個時候,up[i]可以由up[i-1]或者down[i-1]轉化而來
1)如果對於up[i-1], 由於up[i]最後一個元素可以選擇nums[i-1],也可以選擇nums[i],但二者不能同時選擇,其實是平替關係
即 up[i] = up[i-1];
2)如果對於down[i-1],由於down[i-1]最後一個元素可能不是nums[i-1],而是nums[j],
且存在nums[j] > nums[i]的情況下,所以我們需要討論一下是否能找出一種匹配情況?
其實很簡單,down[i-1]最後一個元素不是nums[i-1],且nums[j] > nums[i] > nums[i-1]
那麼我將

最終結果是:
\(\begin{aligned}&up[i]=\begin{cases}up[i-1],&nums[i]\leq nums[i-1]\\\max(up[i-1],down[i-1]+1),&nums[i]>nums[i-1]\end{cases}\\&down[i]=\begin{cases}down[i-1],&nums[i]\geq nums[i-1]\\\max(up[i-1]+1,down[i-1]),&nums[i]<nums[i-1]\end{cases}\end{aligned}\)

程式碼

  • 語言支援:C++
    C++ Code:

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] = 1; down[0] = 1;
        for(int i = 1; i < n; i++){
            if(nums[i] > nums[i-1]){
                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(up[i-1] + 1, down[i-1]);
            }else{
                up[i] = up[i - 1];
                down[i] = down[i-1];
            }
        }
        return max(up[n-1], down[n-1]);
    }
};

複雜度分析

令 n 為陣列長度。

  • 時間複雜度:\(O(n)\)
  • 空間複雜度:\(O(n)\)

相關文章