摆动序列(力扣376)

2024-04-07 00:12
文章标签 力扣 序列 摆动 376

本文主要是介绍摆动序列(力扣376),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


文章目录

  • 题目
  • 前知
  • 题解
    • 一、思路
    • 二、解题方法
    • 三、Code
  • 总结


在这里插入图片描述

题目

Problem: 376. 摆动序列

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

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

子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列最长子序列的长度

示例 1:

输入:nums = [1,7,4,9,2,5]
输出:6
解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。

示例 2:

输入:nums = [1,17,5,10,13,15,10,5,16,8]
输出:7
解释:这个序列包含几个长度为 7 摆动序列。
其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。

示例 3:

输入:nums = [1,2,3,4,5,6,7,8,9]
输出:2

前知

力扣(LeetCode)第376道题目是“摆动序列”(Wiggle Subsequence),属于动态规划和贪心算法的类型。这道题的要求是找到给定整数序列中最长的摆动子序列的长度。摆动序列是指相邻元素之间的差异在正负之间交替变化。


题解

一、思路

要想得到最大摆动序列的话,只要将单调坡上的结点删除,保留两端的结点,这个坡度就有两个峰值,是局部最优,由局部最优推出全局最优,由于题目只要求返回最大摆动序列的长度,用result变量统计,不用删除结点,用后一个值减去前一个值,得到前prediffcurdiff的值大小,如果prediff < 0 && curdiff > 0 或者 prediff > 0 && curdiff < 0 则可以确定存在峰值需要result++
,还有三种特殊情况在下面的解题方法还需要考虑一下

在这里插入图片描述

二、解题方法

本题大概代码是下面这样的:

//只有一个就返回摆动序列长度为1
if (nums.length <= 1) {return nums.length;
}
//计数
int result = 1;for (int i = 1; i < nums.length; i++) {//得到当前差值int curDiff = nums[i] - nums[i - 1];//如果当前差值和上一个差值为一正一负,出现波动就统计if ((prediff < 0 && curdiff > 0) || (prediff > 0 && curdiff < 0)) {result++;}preDiff = curDiff;
}
return count;

三种特殊情况:

  1. 上下坡中有平坡:统一删除靠近左边平坡的点,到最后一个结点时的情况是prediff = 0 && curdiff < 0也要进行记录,所以左边的prediff都要加上与0判断相等的情况
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0))

image.png

  1. 数组首尾两端:当数组只有两个结点时,无法计算出prediffcurdiff,让左边prediff初始为0,这样三个点会根据情况1自动删除左面的一个结点,统计result加1为2,result初始为1,因为nums数组至少都有一个元素,也就是摆动序列长度为1
//当前差值
int curDiff = 0;
//上一个差值
int preDiff = 0;

image.png

  1. 单调坡中有平坡:prediff不能每走一步都进行更新,要等出现波动时,再让prediff等于curdiff。
    在下图中实际上只有数组首尾的1,4是摆动序列里的,result应该为2,但是在平坡的最后一个2的地方因为每走一步prediff都更新下一步的,所以在2的地方也计算了一个波动,只要把prediff更新操作放到if判断里面即可
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {count++;preDiff = curDiff;  // 注意这里,只在摆动变化的时候更新prediff
}

image.png

三、Code

class Solution {public int wiggleMaxLength(int[] nums) {if (nums.length <= 1) {return nums.length;}//当前差值int curDiff = 0;//上一个差值int preDiff = 0;int count = 1;for (int i = 1; i < nums.length; i++) {//得到当前差值curDiff = nums[i] - nums[i - 1];//如果当前差值和上一个差值为一正一负//等于0的情况表示初始时的preDiffif ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {count++;preDiff = curDiff;}}return count;}
}

总结

以上就是针对这道题的刷题笔记,用到了贪心算法从单调坡度上删除中间的结点保留两端的局部最优解推导出整个序列具有最多的局部峰值,达到最长摆动序列,希望这篇题解能够帮助到你解决这个问题。如果有任何疑问或者建议,欢迎留言讨论🌹

这篇关于摆动序列(力扣376)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/881200

相关文章

uva 10131 最长子序列

题意: 给大象的体重和智商,求体重按从大到小,智商从高到低的最长子序列,并输出路径。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vect

POJ1631最长单调递增子序列

最长单调递增子序列 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokenizer;publ

leetcode105 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3/ \9 20/ \15 7   class Solution {public TreeNode buildTree(int[] pr

两数之和--力扣1

两数之和 题目思路C++代码 题目 思路 根据题目要求,元素不能重复且不需要排序,我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中,使用目标值减去当前循环的nums[i],得到差值,如果我们在map中能够找到这个差值,就说明存在两个整数的和为目标值。 如果没有找到,就将当前循环的nums[i]以及下标i放入map中,以便后续查

day-50 求出最长好子序列 I

思路 二维dp,dp[i][h]表示nums[i] 结尾,且有不超过 h 个下标满足条件的最长好子序列的长度(0<=h<=k),二维数组dp初始值全为1 解题过程 状态转换方程: 1.nums[i]==nums[j],dp[i,h]=Math.max(dp[i,h],dp[j,h]+1) 2.nums[i]!=nums[j],dp[i,h]=Math.max(dp[i,h],dp[j,h-1

力扣第347题 前K个高频元素

前言 记录一下刷题历程 力扣第347题 前K个高频元素 前K个高频元素 原题目: 分析 我们首先使用哈希表来统计数字出现的频率,然后我们使用一个桶排序。我们首先定义一个长度为n+1的数组,对于下图这个示例就是长度为7的数组。为什么需要一个长度为n+1的数组呢?假如说总共有三个数字都为1,那么我们需要把这个1放在数组下标为3的位置,假如说数组长度为n,对于这个例子就是长度为3,那么它的

LeetCode:3177. 求出最长好子序列 II 哈希表+动态规划实现n*k时间复杂度

3177. 求出最长好子序列 II 题目链接 题目描述 给你一个整数数组 nums 和一个非负整数k 。如果一个整数序列 seq 满足在下标范围 [0, seq.length - 2] 中 最多只有 k 个下标i满足 seq[i] != seq[i + 1] ,那么我们称这个整数序列为好序列。请你返回 nums中好子序列的最长长度。 实例1: 输入:nums = [1,2,1,1,3],

用Python实现时间序列模型实战——Day 14: 向量自回归模型 (VAR) 与向量误差修正模型 (VECM)

一、学习内容 1. 向量自回归模型 (VAR) 的基本概念与应用 向量自回归模型 (VAR) 是多元时间序列分析中的一种模型,用于捕捉多个变量之间的相互依赖关系。与单变量自回归模型不同,VAR 模型将多个时间序列作为向量输入,同时对这些变量进行回归分析。 VAR 模型的一般形式为: 其中: ​ 是时间  的变量向量。 是常数向量。​ 是每个时间滞后的回归系数矩阵。​ 是误差项向量,假

时间序列|change point detection

change point detection 被称为变点检测,其基本定义是在一个序列或过程中,当某个统计特性(分布类型、分布参数)在某时间点受系统性因素而非偶然因素影响发生变化,我们就称该时间点为变点。变点识别即利用统计量或统计方法或机器学习方法将该变点位置估计出来。 Change Point Detection的类型 online 指连续观察某一随机过程,监测到变点时停止检验,不运用到

【数据结构与算法 | 灵神题单 | 删除链表篇】力扣3217, 82, 237

总结,删除链表节点问题使用到列表,哈希表,递归比较容易超时,我觉得使用计数排序比较稳,处理起来也不是很难。 1. 力扣3217:从链表中移除在数组中的节点 1.1 题目: 给你一个整数数组 nums 和一个链表的头节点 head。从链表中移除所有存在于 nums 中的节点后,返回修改后的链表的头节点。 示例 1: 输入: nums = [1,2,3], head = [1,2,3,