leetcode 376. Wiggle Subsequence 最长摆动序列 + 动态规划DP + 这道题很棒

忘是亡心i 2022-06-07 02:49 223阅读 0赞

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.

Examples:
Input: [1,7,4,9,2,5]
Output: 6
The entire sequence is a wiggle sequence.

Input: [1,17,5,10,13,15,10,5,16,8]
Output: 7
There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].

Input: [1,2,3,4,5,6,7,8,9]
Output: 2

想了好久没想到怎么做,网上看到了一个DP的做法,真的很妙。

使用用up[i]和down[i]分别记录到第i个元素为止以上升沿和下降沿结束的最长“摆动”序列长度,遍历数组,如果nums[i]>nums[i-1],表明第i-1到第i个元素是上升的,因此up[i]只需在down[i-1]的基础上加1即可,而down[i]保持down[i-1]不变;如果nums[i]

  1. /*
  2. * 用up[i]和down[i]分别记录到第i个元素为止以上升沿和下降沿结束的最长“摆动”
  3. * 序列长度,遍历数组,如果nums[i]>nums[i-1],表明第i-1到第i个元素是上升的,
  4. * 因此up[i]只需在down[i-1]的基础上加1即可,而down[i]保持down[i-1]不变;
  5. * 如果nums[i]<nums[i-1],表明第i-1到第i个元素是下降的,因此down[i]
  6. * 只需在up[i-1]的基础上加1即可,而up[i]保持up[i-1]不变;如果nums[i]==nums[i-1],
  7. * 则up[i]保持up[i-1],down[i]保持down[i-1]。比较最终以上升沿和下降沿结束的
  8. * 最长“摆动”序列长度即可获取最终结果
  9. * */
  10. class Solution
  11. {
  12. public int wiggleMaxLength(int[] nums)
  13. {
  14. if(nums==null || nums.length<=0)
  15. return 0;
  16. int[] up=new int[nums.length];
  17. int[] down=new int[nums.length];
  18. up[0]=down[0]=1;
  19. for(int i=1;i<nums.length;i++)
  20. {
  21. if(nums[i]>nums[i-1])
  22. {
  23. up[i]=down[i-1]+1;
  24. down[i]=down[i-1];
  25. }else if(nums[i]<nums[i-1])
  26. {
  27. up[i]=up[i-1];
  28. down[i]=up[i-1]+1;
  29. }else
  30. {
  31. up[i]=up[i-1];
  32. down[i]=down[i-1];
  33. }
  34. }
  35. return Math.max(up[nums.length-1], down[nums.length-1]);
  36. }
  37. }

下面是C++的做法

很明显这就是一个动态规划DP问题,但是没想清楚怎么做,看了一下答案,就是这么做,这道题太棒啦,很值得学习和反思

代码如下:

  1. #include <iostream>
  2. #include <vector>
  3. #include <map>
  4. #include <unordered_map>
  5. #include <set>
  6. #include <unordered_set>
  7. #include <queue>
  8. #include <stack>
  9. #include <string>
  10. #include <climits>
  11. #include <algorithm>
  12. #include <sstream>
  13. #include <functional>
  14. #include <bitset>
  15. #include <numeric>
  16. #include <cmath>
  17. #include <regex>
  18. using namespace std;
  19. class Solution
  20. {
  21. public:
  22. int wiggleMaxLength(vector<int>& nums)
  23. {
  24. if (nums.size() <= 1)
  25. return nums.size();
  26. vector<int> up(nums.size(), 0);
  27. vector<int> down(nums.size(), 0);
  28. up[0] = down[0] = 1;
  29. for (int i = 1; i < nums.size(); i++)
  30. {
  31. if (nums[i] > nums[i - 1])
  32. {
  33. up[i] = down[i - 1] + 1;
  34. down[i] = down[i - 1];
  35. }else if (nums[i] < nums[i - 1])
  36. {
  37. up[i] = up[i-1];
  38. down[i] = up[i - 1] + 1;
  39. }
  40. else
  41. {
  42. up[i] = up[i - 1];
  43. down[i] = down[i - 1];
  44. }
  45. }
  46. return max(up.back(), down.back());
  47. }
  48. };

发表评论

表情:
评论列表 (有 0 条评论,223人围观)

还没有评论,来说两句吧...

相关阅读

    相关 LeetCode 376. 摆动序列

    解题思路 时间复杂度并不理想,没有想到使用波峰,波谷的o(n)算法。 这个dp也还勉强可以通过。 思路就是先计算出差值,然后对差值数组进行dp即可。 代码