【leetcode】376. 摆动序列

题目内容

376. 摆动序列

思路分析

方法一:贪心

参考资料1

参考资料2

参考资料3

贪心策略:只选极值点,而忽略中间的所有点。

可以贪的原因:只选极值点,可以增大后续元素被选中为摆动序列的概率。详见参考资料2和3中的图。

实际实现时,只需记录极值点的个数。可以按照参考资料1,默认最右端有一个极值点,最左端(-1下标处)有一个与下标0处元素一样的点。设当前差值为cur_diff,上次差值为pre_diff,则当(cur_diff > 0 && pre_diff <= 0) || (cur_diff < 0 && pre_diff >= 0)时,证明当前遍历点的左边出现了极值点,极值点个数+1。

方法二:动态规划

参考资料4

看到这个题目的第一感觉是用动态规划,可惜我没想出来...

官方的题解里有动态规划,但是写的很复杂,不想看了

代码

#include <vector>
#include <math.h>
#include <limits.h>

using namespace std;

// 贪心
// 时间复杂度O(n)
// 空间复杂度O(1)
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
       int n = nums.size();
       if (n <= 1) return n;
       int peak_num = 1;
       int pre_diff = 0;
       for (int i = 1; i < n; ++i) {
          int cur_diff = nums[i] - nums[i - 1];
          if ((cur_diff > 0 && pre_diff <= 0) || 
               (cur_diff < 0 && pre_diff >= 0)) {
                  ++peak_num;
                  
                  // 这个一定要放在if里面,否则会通不过一个很长的测试用例
                  // TODO:为什么?
                  pre_diff = cur_diff; 
          }
       }

       return peak_num;
    }
};

int main() {
   Solution s;
   vector<int> input{ 1,17,5,10,13,15,10,5,16,8 };
   int result = s.wiggleMaxLength(input);
   int a = 0;
}

收获

  • 好难好难好难