LeetCode:376. Wiggle Subsequence

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,最后得到的updown中取最大值再加1即可。

在连续下降或上升时,up或down的值均不会变。

此时updown的值代表上升线与下降线的累加和,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时,摆动序列长度为其本身
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值