376. 摆动序列
解法一:动态规划:
找到一个下标元素可能的状态,是上升序列的末尾还是下降序列的末尾。
// 动态规划
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int n = nums.size();
if (n < 2) return n;
vector<int> up(n), down(n);
up[0] = down[0] = 1;
for (int i = 1; i < n; i++) {
// 当前元素是一个上升的元素
if (nums[i] > nums[i - 1]) {
// 则当前以上升元素结尾的子序列最长可能由,上一个以up结尾的子序列长度和down结尾子序列+1取max
up[i] = max(up[i - 1], down[i - 1] + 1);
down[i] = down[i - 1];
} else if (nums[i] < nums[i - 1]) {
up[i] = up[i - 1];
down[i] = max(down[i - 1], up[i - 1] + 1);
} else {
up[i] = up[i - 1];
down[i] = down[i - 1];
}
}
return max(down[n - 1], up[n - 1]);
}
};
// 降维
class Solution1 {
public:
int wiggleMaxLength(vector<int>& nums) {
int n = nums.size();
if (n < 2) return n;
int down = 1, up = 1;
for (int i = 1; i < n; i++) {
if (nums[i] > nums[i - 1]) {
up = max(up, down + 1);
} else {
down = max(down, up + 1);
}
}
return max(down, up);
}
};
贪心:比较好想
// 贪心,只关注“峰”和“谷”,峰和谷一定在最长的摆动序列中
class Solution2 {
public:
int wiggleMaxLength(vector<int>& nums) {
int n = nums.size();
if (n < 2) return n;
int prev_diff = nums[1] - nums[0];
int res = prev_diff != 0 ? 2 : 1;
for (int i = 2; i < n; i++) {
int diff = nums[i] - nums[i - 1];
// 不是一定要找到峰和谷元素,出现上升或下降趋势,我们就知道一定存在峰或谷,直接可以res++
if ((diff > 0 && prev_diff <= 0) || diff < 0 && prev_diff >= 0) {
res++;
prev_diff = diff;
}
}
return res;
}
};