摆动序列

摆动序列

https://leetcode.cn/problems/wiggle-subsequence/description/

图 0

贪心算法思路:
1、找到峰值,prediff和currdiff一正一负。prediff = nums[i] - nums[i-1],currdiff = nums[i+1] - nums[i]。

(prediff > 0 && currdiff < 0) || (prediff < 0 && currdiff > 0)

图 1

2、特殊情况,遇到平坡的情况
这种坡的特点是坡是峰位。那么我们可以把相同的数字删除到只剩一个,即可得到正确答案,这里选择只保留平坡最右边的元素。也就是说prediff可以等于0。

(prediff >= 0 && currdiff < 0) || (prediff <= 0 && currdiff > 0)

图 2

3、首尾元素
题目中说了,如果只有两个不同的元素,那摆动序列也是 2。如果只有两个元素,但元素是相同的,那么摆动序列只有一个。
因此可以简单的做判断,确定result。

当然可以想的更正规一点,更科学一点。

可以假设,数组最前面还有一个数字,那这个数字应该是什么呢?

之前我们在 讨论 情况一:相同数字连续 的时候, prediff = 0 ,curdiff < 0 或者 >0 也记为波谷。

那么为了规则统一,针对序列[2,5],可以假设为[2,2,5],这样它就有坡度了即 preDiff = 0,如图:

图 3

4、情况四单调坡度有平坡
只考虑上述的三种特殊情况的话,我们忽略了一种情况,即 如果在一个单调坡度上有平坡,例如[1,2,2,2,3,4],如图:

图中,我们可以看出,版本一的代码在三个地方记录峰值,但其实结果因为是 2,因为 单调中的平坡 不能算峰值(即摆动)。

之所以会出问题,是因为我们实时更新了 prediff。那么我们应该什么时候更新 prediff 呢?

我们只需要在 这个坡度 摆动变化的时候,更新 prediff 就行,这样 prediff 在 单调区间有平坡的时候 就不会发生变化,造成我们的误判。

图 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var wiggleMaxLength = function(nums) {
if (nums.length < 2) {
return 1;
}
result = 1
prediff = 0
currdiff = 0
for(let i=0;i<nums.length-1;i++){
currdiff = nums[i + 1] - nums[i]
if((prediff<=0 && currdiff>0) || (prediff>=0 && currdiff<0)){
result++
prediff = currdiff
}
}
return result
};