leetCode 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

>>思路和分析

思路1:贪心思路

  • 局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值
  • 整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列

试试贪心:局部最优推出全局最优,并举不出反例!!!

实际操作上,可以不用做删除操作,由于题目要求的是最长摆动子序列的长度,所以只需要统计数组的局部峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)这也就是贪心所贪的地方。

(1)如何表示一个波动呢?

curdiff = nums[i+1] - nums[i];
prediff = nums[i] - nums[i-1];

如果prediff < 0 && curdiff > 0 或者 prediff > 0 && curdiff < 0 此时就有波动就需要统计

(2)如果出现平坡又该如何解决呢? 我们继续往下看~

平坡有两种:一个是 上下中间有平坡,一个是 单调中间有平坡 

① 情况一:上下坡中有平坡

例如 [1,2,2,2,1],它的摆动序列长度是3,也就是我们在删除的时候要不删除左面的三个2,要不就删除右面的三个2

在图中,当 i 指向第一个2的时候,prediff > 0 && curdiff = 0,当 i 指向最后一个2的时候,prediff = 0 && curdiff < 0

若采用删除左面三个2的规则,那么 当 i 指向第一个2的时候,prediff = 0 && curdiff < 0,也要记录一个峰值。这是由于它是把之前相同的元素都删除留下的峰值

所以这里记录峰值的条件可以允许prediff = 0,也就是:prediff <= 0 && curdiff > 0 或者 prediff >= 0 && curdiff < 0 。也就是说相同数字连续的时候,prediff = 0,curdiff < 0 或者 >0 也就为波谷

② 情况二:数组首尾两端

问题思考(O_O)? 统计峰值时,数组的最左面和最右面如何统计呢?

例子:序列[2,5],摆动序列为2。

上文提到 prediff = nums[i] - nums[i-1] 和 curdiff = nums[i+1] - nums[i] 的时候,可知至少需要三个数字才能计算。因其靠统计差值来计算峰值个数就需要考虑数组最左面和最右面的特殊情况。而此时序列数组只有两个数字,如何将我们的判断规则结合在一起呢?

不妨假设数组前面还有一个数字,也就是将序列[2,5],假设为[2,2,5],此时这就有了坡度prediff = 0。而这正是上文讨论的情况一,那么也可以记为一个波谷

针对以上情况,result 初始为 1 (默认最右面有一个峰值),此时curdiff > 0 && prediff <= 0 ,那么result++ (计算了左面的峰值),最后得到的 result 就是 2(峰值个数是2,也就是摆动序列长度为2)

所以说可以初始化 prediff = 0,result = 1

③ 情况三:单调坡中有平坡

上图中,可以计算峰值结果为3,但其实结果应该为2。这是因为上图是不加限制的实时更新prediff,这会导致 单调中的平坡被算为峰值

什么时候该更新prediff呢?只需要在这个坡度摆动变化的时候,更新prediff就行,这样prediff在单调区间有平坡的时候,就不会发生变化,也就不会产生误判!

class Solution {
public:int wiggleMaxLength(vector<int>& nums) {if(nums.size() <= 1) return nums.size();int prediff = 0; // 前一对差值int curdiff = 0; // 当前一对差值int result = 1; // 记录峰值个数,序列默认序列最右边有一个峰值for(int i=0;i<nums.size()-1;i++) {curdiff = nums[i+1] - nums[i];// prediff=curdiff放在if里面,为的是处理单调有平坡的这种情况if((prediff >=0 && curdiff<0) || (prediff <=0 && curdiff>0)) { // 出现峰值result++;prediff = curdiff; // 注意这里,只在摆动变化的时候更新prediff}}return result;}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

prediff = curdiff 放在 if 里面,为的是处理单调有平坡的这种情况。若放在 if 外面,则会出现上文所述的误判!!!

参考和推荐文章、视频

代码随想录 (programmercarl.com)

贪心算法,寻找摆动有细节!| LeetCode:376.摆动序列_哔哩哔哩_bilibili

来自代码随想录的课堂截图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/92200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言数据结构】队列-顺序存储(顺序队列)

队列-顺序存储 代码实现 代码实现 #include<stdio.h> #include<stdlib.h> #include<stdbool.h>#define MaxSize 100 #define ElemType inttypedef struct{//定义队列数据元素ElemType data[MaxSize];//定义队头和队尾指针&#xff08;说是指针&#xff0c;其…

中位数C++题解

T3 中位数 题目描述&#xff1a; 在玩正整数。他手里有一个串&#xff0c;每次会实施三种操作中的一种。 把没有加入的最小的正整数&#xff0c;从左边加入串中。把没有加入的最小的正整数&#xff0c;从右边加入串中。询问此时串的最中间的数&#xff0c;也就是假设当前有 个…

labview 混合信号图 多曲线分组

如果你遇到了混合信号图 多曲线分组显示的问题&#xff0c;本文能给你帮助。 在文章的最好&#xff0c;列出了参考程序下载链接。 一个混合信号图中可包含多个绘图区域。 但一个绘图区域仅能显示数字曲线或者模拟曲线之一&#xff0c;无法兼有二者。 以下显示的分两组&#…

ARM汇编基础指令整合

汇编语言的组成 伪操作 不参与程序的执行&#xff0c;但是用于告诉编译器程序该怎么编译 如&#xff1a; .text .global .end .if .else .endif .data 汇编指令 汇编器将一条汇编指令编译成一条机器码&#xff0c;在内存里一条指令…

RSA算法

算法简介 RSA是一种非对称加密方式。发送者把明文通过公钥加密后发送出去&#xff0c;接受者把密文通过私钥解密得到明文。 算法过程 生成公钥和私钥 选取两个质数p和q&#xff0c;np*q。n的长度就是密钥长度。φ(n)(p-1)*(q-1)φ(n)为n的欧拉函数。找到1-φ(n)间与φ(n)互质的…

DTO的作用

DTO只是一个代码规范的设计&#xff0c;无需过度执着于DTO。在小型项目中&#xff0c;很多情况没有必要使用DTO返回数据&#xff0c;直接用map也完全可以。 减少多余的参数&#xff0c;出于安全性、节约流量的考虑。 例如&#xff1a;密码&#xff0c;出于安全性考虑不返回前端…

公众号商城小程序的作用是什么

公众号是微信平台重要的生态体系之一&#xff0c;它可以与其它体系连接实现多种效果&#xff0c;同时公众号内容创作者非常多&#xff0c;个人或企业商家等&#xff0c;会通过公众号分享信息或获得收益等&#xff0c;而当商家需要在微信做私域经营或想要转化粉丝、售卖产品时就…

BL808学习日志-1-三核通讯

接上个博客&#xff0c;今天实验了一下BL808的IPC通讯&#xff0c;使用的是博流自己的SDK&#xff1b;参考手册上并没有说明各个寄存器&#xff0c;是通过网友的结论和自己的部分修改达成的。 一、实验代码 1.目前仅测试了LP内核和M0内核之间的通讯&#xff0c;使用SIPEED的M…

SELinux 介绍

背景 在工作中经常需要在 android 中增加一些东西&#xff0c; 而android有自己的安全限制&#xff0c;如果不懂SELinux&#xff0c;就不好添加。 Control Access Model https://zh.wikipedia.org/wiki/Chmod https://linux.die.net/man/1/chcon DAC DAC and Trojan Horses D…

一维数组和二维数组的使用(一)

目录 导读1. 一维数组1.1 一维数组的创建1.2 数组的初始化1.3 一维数组的使用1.4 一维数组在内存中的存储 2. 二维数组2.1 二维数组的创建2.2 二维数组的初始化2.3 二维数组的使用2.4 二维数组在内存中的存储 博主有话说 导读 本篇主要讲解一维数组和二维数组的创建和使用&…

dart flutter json 转 model 常用库对比 json_serializable json_model JsonToDart

1.对比 我是一个初学者,一直跟着教材用原生的json,最近发现实在太麻烦了.所以搜索了一下,发现真的有很多现成的解决方案. 网页 https://app.quicktype.io/?ldart 这个是测试下来最好用的 有很多选项,可以使用 json_serializable 也可以不使用 json_serializable 这是推荐最…

机器人入门(一)

机器人入门&#xff08;一&#xff09; 一、ROS是什么&#xff0c;能用来干什么&#xff1f;二、哪些机器人用到了ROS&#xff1f;三、ROS和操作系统是绑定的吗&#xff1f;四、ROS 1 和ROS 2的关系是什么&#xff1f;4.1架构中间件改变API改变数据格式改变 4.2特性4.3工具/生态…

前缀、中缀、后缀表达式相互转换工具

目录 1. 界面一览 2. 使用说明 3. 实例演示 3.1 输入中缀 3.2 输入前缀 3.3 输入后缀 3.4 选择错误的类型 4. 代码 5. 资源地址 关于什么是前缀、中缀、后缀表达式&#xff0c;相信你不知道这个东西&#xff0c;那你也不会点进来这篇博客&#xff0c;当然&#xff0c;…

光鉴科技:以3D视觉变革重新定义驾乘体验

以下文章来源于智车行家 ,作者小易

信息化发展73

数字经济 数字经济是继农业经济、工业经济之后的更高级经济形态。从本质上看&#xff0c;数字经济是一种新的技术经济范式&#xff0c;它建立在信息与通信技术的重大突破的基础上&#xff0c;以数字技术与实体经济融合驱动的产业梯次转型和经济创新发展的主引擎&#xff0c;在…

计算机竞赛 深度学习机器视觉车道线识别与检测 -自动驾驶

文章目录 1 前言2 先上成果3 车道线4 问题抽象(建立模型)5 帧掩码(Frame Mask)6 车道检测的图像预处理7 图像阈值化8 霍夫线变换9 实现车道检测9.1 帧掩码创建9.2 图像预处理9.2.1 图像阈值化9.2.2 霍夫线变换 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分…

CentOS上网卡不显示的问题

文章目录 1.问题描述 1.问题描述 ifconfig下看不到ens33网卡了。systemctl status network #查看网卡状态报下面的问题网上说的解决方式有以下三种&#xff1a; 第一种&#xff1a; 和 NetworkManager 服务有冲突&#xff0c;这个好解决&#xff0c;直接关闭 NetworkManger 服…

竞赛选题 大数据疫情分析及可视化系统

文章目录 0 前言2 开发简介3 数据集4 实现技术4.1 系统架构4.2 开发环境4.3 疫情地图4.3.1 填充图(Choropleth maps)4.3.2 气泡图 4.4 全国疫情实时追踪4.6 其他页面 5 关键代码最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 大数据疫…

【Linux】——基操指令(二)

个人主页 代码仓库 C语言专栏 初阶数据结构专栏 Linux专栏 LeetCode刷题 算法专栏 目录 前言 man指令 cp 指令 mv指令 echo指令 cat指令 more指令 less指令 head和tail指令 head指令 tail指令 前言 上篇文章给大家讲解了Linux环境下的一点基操指令&#xf…

消息队列实现进程之间通信方式代码,现象

消息队列 #include <myhead.h> //消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_ds; #define SIZE sizeof(Msg_ds)-sizeof(long) //正文大小int main(int argc, const char *argv[]) {//1、创建key值key_t …