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.

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?


方法1:

先来DP法,对于从index=0到当前位置index=i这段,用dp[i]表示最大的wiggle sequence长度,这个长度肯定是由前面某个位置+1得到的,而前面某个位置对应的差值数组中的元素可能为正,也可能为负,所以需要两组dp来记录,分别表示当前差值为正和当前差值为负所能取到的最大长度。

举例1,序列[1,17,5,10,13,15,10,5,16,8]对应的dp序列

 1175101315105168
+1224444266
-1133335537

举例2,序列[1,8,7,5,6,4,5,6,9]对应的DP序列

 187564569
+122242666
-113335531


状态转移方程

dp[i][0]=max{dp[j][1]}+1  当nums[i]>nums[j]

dp[i][1]=max{dp[j][0]}+1  当nums[i]<nums[j]

其中 0<=j<i


复杂度O(N^2)

public class Solution {
    public static int wiggleMaxLength(int[] nums)
	{
		int len=nums.length;
		if(len<=1)
			return len;
		
		int[][] dp=new int[len][2];
		dp[0][0]=1;
		dp[0][1]=1;
		
		for(int i=1;i<len;i++)
		{

			int a=Integer.MIN_VALUE;
			int b=Integer.MIN_VALUE;
			for(int k=i-1;k>=0;k--)
			{
				if(nums[i]>nums[k])
					a=Math.max(a, dp[k][1]);
				else if(nums[i]<nums[k])
					b=Math.max(b, dp[k][0]);
			}
			
		
			dp[i][0]=(a>Integer.MIN_VALUE?a+1:1);
			dp[i][1]=(b>Integer.MIN_VALUE?b+1:1);
			
		}
		
		return Math.max(dp[len-1][0], dp[len-1][1]);
	}
}


--------------------------------------------------------------------------------

方法2,贪心


从序列的长度对应关系可以看出

[1,17,5,10,13,15,10,5,16,8]对应的wiggle sequence长度是

[1, 2, 3, 4,  4,  3,  5, 5, 6, 6],可以发现连续的升序或者降序(局部升序或者降序>=3个元素),长度不再增加,按照这个思路,可以得到一个

O(N)的贪心策略解法


代码来自https://discuss.leetcode.com/topic/51811/java-o-n-greedy-solution


public class Solution {
    public int wiggleMaxLength(int[] nums) {
        if(nums.length <= 1) return nums.length;
        int count = 1;
        Boolean prevInc = null;
        for(int i = 1; i < nums.length; i++) {
            if(nums[i] > nums[i - 1] && (prevInc == null || !prevInc)) {
                prevInc = true;
                count++;
            } else if(nums[i] < nums[i - 1] && (prevInc == null || prevInc)) {
                prevInc = false;
                count++;
            }
        }
        return count;
    }
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值