【LeetCode】每日一題376. 擺動序列
阿新 • • 發佈:2020-12-19
技術標籤:每日一題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 也可以,因為我看錯題了,以為要返回結果集~。
- 如果當前數字大於上一個數:
- 前面是上坡,那麼當前的坡更陡,刪除上一個數字,加入當前數字,狀態依然為上坡
- 前面是下坡,加入當前數字,狀態改為上坡
- 如果當前數字小於上一個數:
- 前面是上坡,加入當前數字,狀態更新為下坡
- 前面是下坡,那麼當前更低,刪除上一個數字,加入當前數字,狀態依然為下坡
- 返回容器長度
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 個數為下坡時擺動序列的最大長度
狀態轉移:
-
當前數字大於上一個數時,本次為上坡
- 上坡狀態 up[i],可以從上一次的上坡狀態up[i - 1] 和上一次的下坡狀態[i - i] + 1 的較大者轉移過來
- 下坡狀態保持不變,即 down[i] = down[i - 1]
-
當前數字小於上一個數時,本次為下坡
- 下坡狀態 down[i],可以從上一次的下坡狀態 down[i - 1] 和 上一次的上坡狀態up[i - 1] + 1 的較大者轉移過來
- 上坡狀態保持不變,即 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]);
}