【动归】B019_最长摆动序列(dp)

一、题目描述

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。
第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。

例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。
相反, [1,4,7,2,5][1,7,4,5,5] 不是摆动序列,
第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

给定一个整数序列,返回作为摆动序列的最长子序列的长度。 
通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。

输入: [1,7,4,9,2,5]
输出: 6 
解释: 整个序列均为摆动序列。

二、题解

方法一:dp

  • 定义状态
    • d p [ i ] dp[i] 表示 nums 位置 i 的最长摆动序列的长度。
  • 思考状态转移方程
    • 如果数字之间的差是异号,即 diff[i] × diff[i-1] < 0 d p [ i ] = d p [ i 1 ] + 1 dp[i] = dp[i-1] + 1 ,表示最长摆动序列的长度加1。
  • 思考初始化:
    • d p [ 0... l e n ] = 2 dp[0...len] = 2 表示数组至少有两个不重复的数可以组成摆动序列。
  • 思考输出 d p [ l e n ] dp[len]
public int wiggleMaxLength(int[] nums) {
  int N = nums.length;
  if (N <= 1) return N;

  int[] diff = new int[N];
  int len = 0;
  //去除相邻的重复数
  for(int i = 1; i < N; i++) {
    if (nums[i] != nums[i-1])
      diff[len++] = nums[i] - nums[i-1];
  }
  
  if (len == 0) return 1;	//如果len==0,N >= 2证明相邻的N个数重复是重复的
  int[] dp = new int[len + 1];
  Arrays.fill(dp, 2);		//数组至少有两个数可以组摆动数组
  for (int i = 1; i <= len; i++) {
    if (diff[i] * diff[i-1] < 0)
      dp[i] = dp[i-1] + 1;
    else
      dp[i] = dp[i-1];
  }
  return dp[len];
}

复杂度分析

  • 时间复杂度: O ( N ) O(N)
  • 空间复杂度: O ( N ) O(N)

方法二:状态机


复杂度分析

  • 时间复杂度: O ( ) O()
  • 空间复杂度: O ( ) O()
发布了461 篇原创文章 · 获赞 102 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/104716700