如果連續數字之間的差嚴格地在正數和負數之間交替,則數字序列稱爲擺動序列。第一個差(如果存在的話)可能是正數或負數。少於兩個元素的序列也是擺動序列。
例如, [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);
}
};