LeetCode C++ 376. Wiggle Subsequence【Dynamic Programming】中等
A sequence of numbers is called a wiggle sequence if the differences between successive numbers strictly alternate between positive and negative. The first difference (if one exists) may be either positive or negative. A sequence with fewer than two elements is trivially a wiggle sequence.
For example, [1,7,4,9,2,5]
is a wiggle sequence because the differences (6,-3,5,-7,3)
are alternately positive and negative. In contrast, [1,4,7,2,5]
and [1,7,4,5,5]
are not wiggle sequences, the first because its first two differences are positive and the second because its last difference is zero.
Given a sequence of integers, return the length of the longest subsequence that is a wiggle sequence. A subsequence is obtained by deleting some number of elements (eventually, also zero) from the original sequence, leaving the remaining elements in their original order.
Example 1:
Input: [1,7,4,9,2,5]
Output: 6
Explanation: The entire sequence is a wiggle sequence.
Example 2:
Input: [1,17,5,10,13,15,10,5,16,8]
Output: 7
Explanation: There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].
Example 3:
Input: [1,2,3,4,5,6,7,8,9]
Output: 2
Follow up: Can you do it in O(n)
time?
題意:如果連續數字之間的差嚴格地在正數和負數之間交替,則數字序列稱為擺動序列。第一個差(如果存在的話)可能是正數或負數。少於兩個元素的序列也是擺動序列。
例如, [1,7,4,9,2,5]
是一個擺動序列,因為差值 (6,-3,5,-7,3)
是正負交替出現的。相反 [1,4,7,2,5]
和 [1,7,4,5,5]
不是擺動序列,第一個序列是因為它的前兩個差值都是正數,第二個序列是因為它的最後一個差值為零。
給定一個整數序列,返回作為擺動序列的最長子序列的長度。 通過從原始序列中刪除一些(也可以不刪除)元素來獲得子序列,剩下的元素保持其原始順序。
解法 動態規劃
連續數字之間的差嚴格地在正數和負數之間交替,這種說法不太直觀——無非是 A[i - 1] < A[i] > A[i + 1]
或者 A[i - 1] > A[i] < A[i + 1]
這樣的變化序列。
應用最長遞增子序列的思想,得到 O ( n 2 ) O(n^2) O(n2) 的一個解法。具體程式碼如下:
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
if (nums.empty()) return 0;
int n = nums.size(), ans = 1;
//dp[i][0]表示以nums[i]為上升結尾的最長擺動序列長度
//dp[i][1]表示以nums[i]為下降結尾的最長擺動序列長度
vector<vector<int>> dp(n, vector<int>(2));
dp[0][0] = dp[0][1] = 1;
for (int i = 1; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (nums[i] < nums[j]) dp[i][1] = max(dp[i][1], dp[j][0] + 1); //能夠以nums[i]為下降結尾
else if (nums[i] > nums[j]) dp[i][0] = max(dp[i][0], dp[j][1] + 1); //能夠以nums[i]為上升結尾
}
ans = max(ans, max(dp[i][0], dp[i][1]));
}
return ans;
}
};
執行效率如下:
執行用時:28 ms, 在所有 C++ 提交中擊敗了6.27% 的使用者
記憶體消耗:7.9 MB, 在所有 C++ 提交中擊敗了5.06% 的使用者
優化為 O ( n ) O(n) O(n) 演算法:
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
if (nums.empty()) return 0;
int n = nums.size(), ans = 1;
vector<vector<int>> dp(n, vector<int>(2));
dp[0][0] = dp[0][1] = 1;
for (int i = 1; i < n; ++i) {
if (nums[i] > nums[i - 1]) {//nums[i-1]到nums[i]上升
dp[i][0] = max(dp[i - 1][1] + 1, dp[i - 1][0]);
dp[i][1] = dp[i - 1][1];
} else if (nums[i] < nums[i - 1]) {
dp[i][0] = dp[i - 1][0];
dp[i][1] = max(dp[i - 1][0] + 1, dp[i - 1][1]);
} else {
dp[i][0] = dp[i - 1][0];
dp[i][1] = dp[i - 1][1];
}
ans = max(ans, max(dp[i][0], dp[i][1]));
}
return ans;
}
};
執行效率如下:
執行用時:4 ms, 在所有 C++ 提交中擊敗了48.95% 的使用者
記憶體消耗:7.7 MB, 在所有 C++ 提交中擊敗了5.06% 的使用者
相關文章
- [LeetCode] 280. Wiggle SortLeetCode
- LeetCode C++ 50. Pow(x, n)【Recursion】中等LeetCodeC++
- LeetCode 376. 擺動序列LeetCode
- leetcode392. Is SubsequenceLeetCode
- LeetCode C++ 56. Merge Intervals【排序/陣列】中等LeetCodeC++排序陣列
- 動態規劃(Dynamic programming)動態規劃
- Y 分鐘速成 Dynamic Programming
- LeetCode C++ 316. Remove Duplicate Letters【Stack/Greedy/String】中等LeetCodeC++REM
- LeetCode C++ 1302. Deepest Leaves Sum【Tree/BFS/DFS】中等LeetCodeC++
- LeetCode C++ 33. Search in Rotated Sorted Array【二分】中等LeetCodeC++
- [LeetCode] 727. Minimum Window SubsequenceLeetCode
- js解leetcode(32)-中等JSLeetCode
- 【Leetcode】1081. Smallest Subsequence of Distinct CharactersLeetCode
- 【Leetcode】1673. Find the Most Competitive SubsequenceLeetCode
- [LeetCode] 674. Longest Continuous Increasing SubsequenceLeetCode
- LeetCode C++ 劍指 Offer 64. 求1+2+…+n【Bit Manipulation】中等LeetCodeC++
- [LeetCode] 2825. Make String a Subsequence Using Cyclic IncrementsLeetCodeREM
- JAVA-LeetCode中等29兩數相除JavaLeetCode
- LeetCode-5426、重新規劃路線-中等LeetCode
- 動態規劃(dynamic programming)與貪心演算法(greedy algorithm)動態規劃演算法Go
- 【leetcode】LCP 19. 秋葉收藏集(UlBDOe)(DP)[中等]LeetCode
- 【LeetCode刷題(中等程度)】946. 驗證棧序列LeetCode
- RBE104TC C/C++ Programming LanguageC++
- [LeetCode 中等 動態規劃 ]221. 最大正方形LeetCode動態規劃
- leetcode:面試題 01.08. 零矩陣(陣列,中等)LeetCode面試題矩陣陣列
- LeetCode: 1052. 愛生氣的書店老闆(中等)LeetCode
- Missing Subsequence Sum
- 【LeetCode刷題(中等程度)】662. 二叉樹最大寬度LeetCode二叉樹
- 力扣-376. 擺動序列力扣
- Lintcode 1263. Is Subsequence
- leetcode 整數拆分(c++)LeetCodeC++
- AI學習筆記——強化學習之動態規劃(Dynamic Programming)解決MDP(1)AI筆記強化學習動態規劃
- 【Leetcode 346/700】79. 單詞搜尋 【中等】【回溯深度搜尋JavaScript版】LeetCodeJavaScript
- B. Missing Subsequence Sum
- [atcoder 349] [F - Subsequence LCM]
- 【10月打卡~Leetcode每日一題】18. 四數之和(難度:中等)LeetCode每日一題
- leetcode:462. 最少移動次數使陣列元素相等 II(數學,中等)LeetCode陣列
- leetcode 831題解【C++/Java/Python】LeetCodeC++JavaPython