Description
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
Follow up:
Can you do it in O(n) time?
题意:求最长摆动序列。如图所示,最长摆动序列长度为6
。
Solution
思路:通过图片可以发现摆动序列的长度其实就是上升线数量和下降线数量之和再加 1,如上图,上升线有3条,下降线有 2 条,则最长摆动序列为3+2+1
此外,需要考虑初始序列中元素个数小于 2 个的情况,以及需要排除水平线的情况(即前后元素相等)
代码如下:
public static int wiggleMaxLength(int[] nums) {
int down=0,up=0;//下降线和上升线计数器
boolean flag = true;//记录第一条是上升线还是下降线,true为上升线
int j=1;
for( ; j<nums.length; j++){
if(nums[j-1]>nums[j]){
down++;
flag = false;
break;
} else if(nums[j-1]<nums[j]){
up++;
break;
}
}
for(int i=j+1; i<nums.length; i++){
if(!flag && nums[i] > nums[i-1]){//若前一条为下降线,下一条转为上升则上升线计数器加一
flag = true;
up++;
} else if(flag && nums[i] < nums[i-1]){//若上一条为上升线,下一条转为下降则下降线计数器加一
flag = false;
down++;
}
}
return nums.length < 2 ? nums.length : down+up+1;
}
在上述代码的基础上,进行简化代码,由于我们只需要记录上升线与下降线的数量,并且最后求和,因此我们可以将求和的操作分散在每一次的循环中,将递增改为求和,即累加上升线与下降线,例如在转折下降处,将down++
改为down=up+1
,最后得到的up
和down
中取最大值再加1
即可。
在连续下降或上升时,up或down的值均不会变。
此时up
或down
的值代表上升线与下降线的累加和,up
表示最后一条为上升线时的累加和,down
表示最后一条是下降线时的累加和。
代码:
public static int wiggleMaxLength(int[] nums) {
int up=1,down=1;//将最后的加1操作放在初始化中
for(int i=1; i<nums.length; i++){
if(nums[i] > nums[i-1]){//上升线
up=down+1;
} else if(nums[i] < nums[i-1]){//下降线
down=up+1;
}
}
int res=up>down?up:down;//取最大值
return nums.length<2?nums.length:res;//当序列元素个数小于2时,摆动序列长度为其本身
}