1. 程式人生 > 其它 >【LeetCode】每日一題376. 擺動序列

【LeetCode】每日一題376. 擺動序列

技術標籤:每日一題leetcodejava演算法動態規劃貪心演算法

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

進階:

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

方法一:貪心

先說下為什麼用 stack,當然 list 也可以,因為我看錯題了,以為要返回結果集~。

  • 如果當前數字大於上一個數:
    1. 前面是上坡,那麼當前的坡更陡,刪除上一個數字,加入當前數字,狀態依然為上坡
    2. 前面是下坡,加入當前數字,狀態改為上坡
  • 如果當前數字小於上一個數:
    1. 前面是上坡,加入當前數字,狀態更新為下坡
    2. 前面是下坡,那麼當前更低,刪除上一個數字,加入當前數字,狀態依然為下坡
  • 返回容器長度
public int wiggleMaxLength(int[] nums) {
    int n = nums.length;
    if (n < 2) {
        return n;
    }
    Stack<Integer> stack = new Stack<>();
    stack.add(nums[0]);
    int status =
0;// 0初始化 1最後是下降 2最後是上升 for (int i = 1; i < n; ++i) { if (nums[i] == stack.peek()) { continue; } if (status == 0) { status = nums[i] > stack.peek() ? 2 : 1; } else if (status == 1) { if (nums[i] > stack.peek()) { status = 2; } else { stack.pop(); } } else { if (nums[i] > stack.peek()) { stack.pop(); } else { status = 1; } } stack.push(nums[i]); } return stack.size(); }

方法二:動態規劃

狀態表達式:

  • up[i] 表示第 i 個數為上坡時擺動序列的最大長度
  • down[i] 表示第 i 個數為下坡時擺動序列的最大長度

狀態轉移:

  • 當前數字大於上一個數時,本次為上坡

    1. 上坡狀態 up[i],可以從上一次的上坡狀態up[i - 1] 和上一次的下坡狀態[i - i] + 1 的較大者轉移過來
    2. 下坡狀態保持不變,即 down[i] = down[i - 1]
  • 當前數字小於上一個數時,本次為下坡

    1. 下坡狀態 down[i],可以從上一次的下坡狀態 down[i - 1] 和 上一次的上坡狀態up[i - 1] + 1 的較大者轉移過來
    2. 上坡狀態保持不變,即 up[i] = up[i - 1]
  • 當前數字等於上一個數,上坡狀態 up[i] = up[i - 1];下坡狀態 down[i] = down[i - 1]

public int wiggleMaxLength(int[] nums) {
    int n = nums.length;
    if (n < 2) {
        return n;
    }

    int[] up = new int[n];
    int[] down = new int[n];
    up[0] = 1;
    down[0] = 1;

    for (int i = 1; i < n; ++i) {
        if (nums[i] > nums[i - 1]) {
            up[i] = Math.max(up[i - 1], down[i - 1] + 1);
            down[i] = down[i - 1];
        } else if (nums[i] < nums[i - 1]) {
            down[i] = Math.max(down[i - 1], up[i - 1] + 1);
            up[i] = up[i - 1];
        } else {
            up[i] = up[i - 1];
            down[i] = down[i - 1];
        }
    }
    return Math.max(up[n - 1], down[n - 1]);
}

執行結果

在這裡插入圖片描述