这道题的意思是寻找一个子序列,这个序列需要满足一定的条件:
1. 不能连续递增或者递减
2. 只能间隔递增或者递减
3. 两数之间的差值必须不为0
对于满足要求的序列[1,7,4,9,2,5],我们可以做一个图:
我们发现这个图形的规律,是不是一上一下或者一下一上,形成一个拐点就是答案呢?
再来看看几种不符合情况的图:
第一种情况:
只需要将标记红色的去除,即可得到wiggle subsequence。去除的数必须是两端中间的节点,如果去除的是两端的节点,那么可能给已经确定的答案造成影响,比如说[1,7,5,10,11,15,12,5,16,8],如下图
那么相对于去除10,11已经形成的答案[1,7,5,15,12]而言,去除5,15所形成的序列[1,7,10,11,12]并不是合法的,因为两端是属于这个阶段的最高或者最低,所能包含的东西会更多
第二种情况:
这种连续上升的情况,也不符合wiggle subsequence
第三种情况:
在初始化的时候,如果数组包含两个不相同的元素,那么答案是2,否则是1。比如说[1,2]得到的答案便是2,而[2,2]得到的答案则是1。然而,如果按照拐点的定义,那么初始化dif = nums[1]-nums[0]时,dif=0,那么dif乘以任何数都为0,岂不是有问题?所以这里将dif变为-1,为了保证dif*tmp<0符合拐点定义。
第四种情况:
这里的情况与第三种情况正好相反,将dif变为1即可。
public class Solution {
public int wiggleMaxLength(int[] nums) {
// 两种情况 [] , [1]
if(nums.length<=1){
return nums.length;
}
int ans = 2;
int dif = nums[1]-nums[0];
//刚开始出现两个数相同 那么初始的答案应该是1而不是 2 [2,2] 的答案是1 [2,1]或[1,2]的答案才是2
//开始时 如果两个数字相同,ans初始化为1
if(dif==0){
ans = 1;
}
for(int i=2;i<nums.length;i++){
int tmp =nums[i]-nums[i-1];
//第三种情况
if(ans==1 && tmp >0){
dif = -1;
//第四种情况
}else if(ans==1 && tmp<0){
dif=1;
}
//如果A,B,C 中(B-A)*(B-C)的乘积小于0 则说明存在拐点 答案ans+1 并且更新差值
if(dif*tmp<0){
ans++;
dif = tmp;
}
}
return ans;
}
}