leetcode 376. Wiggle Subsequence

问题描述

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.

Example 1:

Input: [1,7,4,9,2,5]
Output: 6
Explanation: The entire sequence is a wiggle sequence.

分析

这道题我很快有了自己的思路:计算nums[i]-nums[i-1]的差dif[i-1],并判断dif[i-1]和dif[i-2]是否是异号(相乘是否小于0)。

但是这个思路对于相邻数相等的情况非常不友好。我一开始修改的是if(dif[i-1]*dif[i-2]<0||(dif[i-2]==0&&dif[i-1])),即增加一种情况,如果该数之前的两个相等且dif[i-1]非0时,当前数也可以保留。但这样的解法不对,举一个例子:1,2,2,2,2,4.所以dif[i-1]还要参考前面最接近的非零的dif[*]的正负。当然要注意的是,很有可能前面所有的差值都是0.

所以步骤如下:

先判断前一个差值dif[i-2]是否为0

如果为0:如果前面差值都是0,且dif[i-1]不为0,或者dif[i-1]和前面最接近的非零的dif[*]异号,长度加1

如果不为0:就直接判断dif[i-1]和dif[i-2]是否是异号即可。

注意:代码中我用了dp数组,还可以更优化,将其只用一个变量代替,因为它只有两种可能:不变,或者+1.

代码(不够简洁)

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int len=nums.size();
        if(len==1)
            return 1;
        if(len<=0)
            return 0;
        int flag=0;
        int dp[len];
        int dif[len-1];
        dp[0]=1;
        dif[0]=nums[1]-nums[0];
        if(dif[0]!=0)
            dp[1]=2;
        else dp[1]=1;
        for(int i=2;i<len;i++)
        {
            dif[i-1]=nums[i]-nums[i-1];
            if(dif[i-2]==0)
                if((flag==0&&dif[i-1]!=0)||(flag!=0&&(flag*dif[i-1]<0)))
                dp[i]=dp[i-1]+1;
                else dp[i]=dp[i-1];
            else if(dif[i-1]*dif[i-2]<0)
                dp[i]=dp[i-1]+1;
            else
                dp[i]=dp[i-1];
            if (dif[i-1]!=0)
                flag=dif[i-1];
        }
        return dp[len-1];
    }
};

别人更巧妙的思路:

用up和down两个变量来统计。

如果dif[i-1]<0,说明它是一个下降的趋势,down=up+1;

如果dif[i-1]>0,说明它是一个上升的趋势,up=down+1;

这样交叉的统计非常巧妙。1,4,5,6,up和down初始化为1,

对于1,4,up=down+1=2;

对于4,5,down=up+1=3;

对于5,6,down=up+1=3;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值