Studying-代码随想录训练营day27| 贪心算法理论基础、455.分发饼干、376.摆动序列、53.最大子序和

第27天,贪心开始!(ง •_•)ง💪,编程语言:C++

目录

贪心算法理论基础

贪心的套路

贪心的一般解题步骤

总结 

455.分发饼干

376.摆动序列

53.最大子序和

总结 


贪心算法理论基础

什么是贪心?—— 贪心的本质是选择每一个阶段的局部最优,从而达到全局最优。例如:你可以拿走十张,如果想达到最大的金额,你要怎么拿?指定每次拿最大的,最终结果就是拿走最大数额的钱!

但要注意的是只有局部最优能够推出全局最优,也就是没有反例的情况下,才能够使用贪心算法。因为比如说再举一个例子如果是 有一堆盒子,你有一个背包体积为n,如何把背包尽可能装满,如果还每次选最大的盒子,就不行了,需要考虑了的条件增加了许多,这时候就需要动态规划,而不是贪心了。

贪心的套路

总结:贪心算法没有固定套路。说到底贪心只有一句话通过局部最优,推出整体最优,而能否从局部最优推出整体最优,只能通过思考,模拟,并且举反例的方式来确定。一般来说最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧

对于贪心来说最重要的是能够想到模拟策略,面试中最重要的也是能够自圆其说即可。刷题或者面试的时候,手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心

贪心算法很多情况下都是常识性推导,让人认为本应该就这么做,这也是贪心难的地方,能够想到就能解出,但如果想不到就很难解出了。

贪心的一般解题步骤

贪心算法一般分为四步:

  • 将问题分解为若干个子问题
  • 找出适合的贪心策略
  • 求解每一个子问题的最优解
  • 将局部最优解堆叠成全局最优解

但事实上以上四步有些过于理想化,我们做题的时候不会说按照这样去思考,因此最重要的还是想清楚局部最优是什么,并且如何推导出全局最优。

总结 

贪心算法没有套路,有的只是常识性的推导和灵感的碰撞。


455.分发饼干

文档讲解:代码随想录分发饼干

视频讲解:手撕分发饼干

题目:

学习:本题算是比较经典的贪心算法之一。首先需要理解题干的意思:有一堆饼干和一群小孩,把饼干分给小孩,但每个小孩只能分得一块饼干。每块饼干具有一个尺寸值,每位小孩具有一个胃口值,只有当尺寸值大于胃口值时,小孩才能够满足。

给予以上分析,可以推出局部最优就是尽可能大尺寸的饼干满足大胃口的人(牢记一块饼干只能给一个人),从而得到总体最优满足最多的人。

根据上述策略,我们首先要对饼干和小孩两个数组进行排序,而后选择尺寸最大的饼干,之后遍历小孩找到符合要求的最大胃口的小孩,接着在选择下一块饼干继续遍历(要注意遍历小孩我们也是从胃口最大的开始遍历,因此选择下一个饼干时我们不需要从头遍历,因为胃口大的那些小孩肯定不会满足尺寸更小的饼干,继续遍历就可以了)

代码:

//时间复杂度O(nlogn + mlogm)两个排序的时间复杂度
//空间复杂度O(1)
class Solution {
public:int findContentChildren(vector<int>& g, vector<int>& s) {int count = 0; //记录小孩数量//先进行排序sort(g.begin(), g.end());sort(s.begin(), s.end());int index = s.size() - 1; //指向最后一个元素,此时为最大饼干for(int i = g.size() - 1; i >= 0 && index >= 0; i--) {if(g[i] <= s[index]) {count++;index--;}}return count;}
};

本题还可以采取小饼干先喂小胃口的人的方法,但此时要注意先选择小胃口的人,然后遍历饼干,因为此时我们需要的是找到满足最小胃口的最小饼干,和前面的找到满足最大饼干的最大胃口是相反的。

代码:

class Solution {
public:int findContentChildren(vector<int>& g, vector<int>& s) {//第二种方法,先遍历胃口再遍历饼干(先满足小胃口的)sort(g.begin(), g.end());sort(s.begin(), s.end());int index = 0;//遍历饼干,找到符合最小胃口的小孩for(int i = 0; i < s.size() && index < g.size(); i++) {if(s[i] >= g[index]) {index++; //查找下一个胃口小的小孩}}return index; //满足了多少个小孩,就是答案数量}
};

376.摆动序列

文档讲解:代码随想录摆动序列

视频讲解:手撕摆动序列

题目:

学习:本题理解题意,摆动序列指的是数字之间的差是正负数摇摆交替的,可以通过删除一些元素,来使得剩余元素组成的序列是摇摆序列。如果仅有一个元素或者含两个不等元素的序列也视作摇摆序列。

首先我们很容易能够想到,找到波峰和波谷,删除中间多余的元素,就能够组成一个摇摆序列。

在解题过程中,我们不需要删除多余的元素,只需要保存波峰和波谷的元素就能够得到元素最多的摆动序列,并且本题甚至只需要返回长度值,不需要我们把元素进行保存。

但本题不能仅仅判断左右差值是否为正负,我们需要考虑除上图情况以外的三种情况:

情况一:上下坡中有平坡

对于这种情况,显然是把中间多余的三个3去除,最后留下(1,2,1)序列,也就是长度为3。但本题2在的位置不是明显的波峰或是波谷,不能通过判断左右差值为正负来进行。因此我们需要单独考虑该情况的逻辑。

当i指向第一个2的时候,prediff > 0 & curdiff = 0,当i指向最后一个2的时候,prediff = 0 && curdiff < 0。这两个条件都可以,但是为了便于我们进行从左到右的遍历,我们这边采用删除左面三个2的规则,因此当prediff = 0 && curdiff < 0时要记录一个峰值,这是上坡的情况。下坡的情况就是prediff = 0 && curdiff > 0的情况也要记录一个峰值。加上前面的判断正负的情况,因此我们要记录峰值的条件应该是:(prediff <= 0 && curdiff > 0) || (prediff >= 0 && curdiff < 0)。

情况二:数组首尾两端

因为本题的要求,如果只有一个元素则摆动序列为1,如果有两个元素且两个元素不同的情况下摆动序列为2。但我们在计算prediff和curdiff的时候,至少需要三个数字才能进行计算。我们可以通过单独列出一个if 来处理当元素只有两个的情况。但我们也可以将其加入到统一的循环当中,那就是让prediff初始 = 0。例如我们针对序列[2,5],可以假设为[2,2,5],这样也就有了坡度。

针对上述情形,我们的result初始为1,默认最右面有一个数值(符合我们上面说的遍历规则)。当出现上述情况的时候,result就会+1,最后得到的就是2。这样也能够处理超过两个数并且所有数都是一样的情况。

情况三:单调坡度有平坡 

可以看出针对这种情况,我们在情况一中使用的方法可能就会带来错误,因为上述的序列,我们最后得到的只能是[1,4]或者时其他长度为2的摆动序列。因此我们这边要注意的是prediff的更新逻辑。prediff不能实时进行更新,它保存的不仅仅是差值还应是数组的一个趋势,因此prediff应该在有坡度摆动变化的时候进行更新,也就是出现峰值的时候我们再进行更新。

代码:解决上述三种情况后,可以得到代码:

//时间复杂度O(n)
//空间复杂度O(1)
class Solution {
public:int wiggleMaxLength(vector<int>& nums) {if (nums.size() == 1) return 1; //如果只有一个元素,返回1int prediff = 0; //前端差值int curdiff = 0; //后段差值int result = 1; //记录结果,默认加入尾元素,首元素单独处理,防止出现所有元素都相同的情况//不遍历尾元素for (int i = 0; i < nums.size() - 1; i++) {curdiff = nums[i + 1] - nums[i];//出现峰值if((prediff >= 0 && curdiff < 0) || (prediff <= 0 && curdiff > 0)) {result++;prediff = curdiff; //当需要记录结果的时候,再改变前端差值,保证当前数组趋势}}return result;}
};

53.最大子序和

文档讲解:代码随想录最大子序和

视频讲解:手撕最大子序和

题目:

学习:本题显然可以通过两个for循环进行暴力求解。但本题同样也可以使用贪心算法来降低时间复杂度。本题的贪心逻辑在于我们从头开始遍历的过程中,如果发现加和为负数,就立马抛弃目前的“连续和”,因为负数参与加和只会使得数变小,而不会变大。因此我们需要立马抛弃该和,从下一个元素重新计算“连续和”,由这种局部最优的方式来推导出全局最优。

注意:我们是在加和为负数的情况下,才去抛弃“连续和”,而不是遇到负数就抛弃,两者是有区别的,因为加和还不为负数时,仍然是可以给后面的数提供加大的可能性的。但我们也要通过设置一个maxcount实时记录当前count的最大值,这样也能够避免我们因为存在负数而错过最大值的情况。

因为本题不需要我们记录最大序列的左右下标,因此本题设置一个result或者maxcount记录最大值就可以了,否则还需要设置两个左右端点来记录下标。

代码:

//时间复杂度O(n)
//空间复杂度O(1)
class Solution {
public:int maxSubArray(vector<int>& nums) {int count = 0; //记录当前和int maxcount = INT_MIN; //记录最大值for(int i = 0; i < nums.size(); i++) {//如果当前和小于0,抛弃前和,改为当前值if(count < 0) {count = nums[i];}else {count += nums[i];}//如果当前和大于最大值,更新最大值if (count > maxcount) {maxcount = count;}}return maxcount;}
};

总结 

贪心算法更重要的是考察逻辑思维能力,找到局部最优推出总体最优的方法,要尝试进行模拟,并推出反例,如果推不出反例就大胆尝试使用贪心方法。

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

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

相关文章

计算机组成原理学习笔记(一)

计算机组成原理 [类型:: [[计算机基础课程]] ] [来源:: [[B站]] ] [主讲人:: [[咸鱼学长]] ] [评价:: ] [知识点:: [[系统软件]] & [[应用软件]] ] [简单解释:: 管理计算机系统的软件&#xff1b; 按照任务需要编写的程序 ] [问题:: ] [知识点:: [[机器字长]] ] [简单…

三相感应电机的建模仿真(2)基于ABC相坐标系S-Fun的仿真模型

1. 概述 2. 三相感应电动机状态方程式 3. 基于S-Function的仿真模型建立 4. 瞬态分析实例 5. 总结 6. 参考文献 1. 概述 前面建立的三相感应电机在ABC相坐标系下的数学模型是一组周期性变系数微分方程&#xff08;其电感矩阵是转子位置角的函数&#xff0c;转子位置角随时…

ubuntu22 sshd设置

专栏总目录 一、安装sshd服务 sudo apt updatesudo apt install -y openssh-server 二、配置sshd 使用文本编辑器打开/etc/ssh/sshd_config sudo vi /etc/ssh/sshd_config &#xff08;一&#xff09;配置sshd服务的侦听端口 建议将ssh的侦听端口改为7000以上的端口&#…

安装 tesseract

安装 tesseract 1. Ubuntu-24.04 安装 tesseract2. Ubuntu-24.04 安装支持语言3. Windows 安装 tesseract4. Oracle Linux 8 安装 tesseract 1. Ubuntu-24.04 安装 tesseract sudo apt install tesseract-ocr sudo apt install libtesseract-devreference: https://tesseract-…

Android- Framework 非Root权限实现修改hosts

一、背景 修改system/etc/hosts&#xff0c;需要具备root权限&#xff0c;而且remount后&#xff0c;才能修改&#xff0c;本文介绍非root状态下修改system/etc/hosts方案。 环境&#xff1a;高通 Android 13 二、方案 非root&#xff0c;system/etc/hosts只有只读权限&…

【分布式系统】ELK 企业级日志分析系统

目录 一.ELK概述 1.简介 1.1.可以添加的其他组件 1.2.filebeat 结合 logstash 带来好处 2.为什么使用ELK 3.完整日志系统基本特征 4.工作原理 二.部署ELK日志分析系统 1.初始化环境 2.完成JAVA部署 三. ELK Elasticsearch 集群部署 1.安装 2.修改配置文件 3.es 性…

Linux运维之管道符、重定向与环境变量

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 目录 一、输入输出重定向 二、管道命令符 三、命令行的通配符 四、常用的转义字符 五、重要的环境变量 致谢 一、输入输出重定向 输入重定向是…

《昇思25天学习打卡营第13天|onereal》

今天学习的内容如下&#xff1a; DCGN生成漫画头像 在下面的教程中&#xff0c;我们将通过示例代码说明DCGAN网络如何设置网络、优化器、如何计算损失函数以及如何初始化模型权重。在本教程中&#xff0c;使用的动漫头像数据集共有70,171张动漫头像图片&#xff0c;图片大小均为…

进程控制-exec函数

让父子进程来执行不相干的操作 能够替换进程地址空间的代码.text段 执行另外的程序&#xff0c;不需要创建额外的的地址空间 当前程序中调用另外一个应用程序 指定执行目录下的程序 int execl(const char *path, const char *arg&#xff0c;/* (char *) NULL */); /* pat…

[学习笔记]SQL学习笔记(连载中。。。)

学习视频&#xff1a;【数据库】SQL 3小时快速入门 #数据库教程 #SQL教程 #MySQL教程 #database#Python连接数据库 目录 1.SQL的基础知识1.1.表(table)和键(key)1.2.外键、联合主键 2.MySQL安装&#xff08;略&#xff0c;请自行参考视频&#xff09;3.基本的MySQL语法3.1.规…

2024年最新运维面试题(附答案)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 一&#xff0e;选择题 1.HTTP协议默认使用哪个端口…

html的作业

目录 作业题目 1.用户注册 A图 B代码 2.工商银行电子汇款单 A图 B代码 3.李白诗词 A图 B代码 4.豆瓣电影 A图 B代码 学习产出&#xff1a; 作业题目 1.用户注册 A图 B代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset&qu…

均匀采样信号的鲁棒Savistky-Golay滤波(MATLAB)

S-G滤波器又称S-G卷积平滑器&#xff0c;它是一种特殊的低通滤波器&#xff0c;用来平滑噪声数据。该滤波器被广泛地运用于信号去噪&#xff0c;采用在时域内基于多项式最小二乘法及窗口移动实现最佳拟合的方法。与通常的滤波器要经过时域&#xff0d;频域&#xff0d;时域变换…

进程的初步认识

目录 一、硬件方面介绍 1.冯诺依曼体系结构 2.存储分级 二、软件 方面 1.操作系统是一款进行管理的软件&#xff0c;它可以管理硬件也可以管理软件 2.操作系统如何管理&#xff1f; 三、进程 1.概念 总结 四、linux中对进程的管理 1.task_ struct内容分类 2.查看进…

解决Linux环境Qt报“cannot find -lgl“问题

今天&#xff0c;在Ubuntu 18.04.6环境下&#xff0c;安装Qt5.14.2之后&#xff0c;运行一个QWidget工程&#xff0c;发现Qt报"cannot find -lgl"错误。     出现这种现象的原因&#xff1a;Qt的Path路径没有配置&#xff0c;缺少libqt4-dev依赖包和一些必要的组件…

Redis基础教程(九):redis有序集合

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

从“钓”到“管”:EasyCVR一体化视频解决方案助力水域安全管理

一、背景 随着城市化进程的加快&#xff0c;越来越多的市民热衷于钓鱼活动。钓鱼活动在带来乐趣的同时&#xff0c;也伴随着一定的安全隐患。尤其是在一些危险水域&#xff0c;也经常出现垂钓者的身影&#xff0c;非法垂钓&#xff0c;这给城市管理带来了不小的阻力。传统的人…

如何处理 PostgreSQL 中由于表连接顺序不当导致的性能问题?

文章目录 一、理解表连接和连接顺序二、识别由于表连接顺序不当导致的性能问题三、影响表连接顺序的因素四、解决方案手动调整连接顺序创建合适的索引分析数据分布和优化查询逻辑 五、示例分析手动调整连接顺序创建索引优化查询逻辑 六、总结 在 PostgreSQL 中&#xff0c;表连…

【Docker安装】OpenEuler系统下部署Docker环境

【Docker安装】OpenEuler系统下部署Docker环境 前言一、本次实践介绍1.1 本次实践规划1.2 本次实践简介二、检查本地环境2.1 检查操作系统版本2.2 检查内核版本2.3 检查yum仓库三、卸载Docker四、部署Docker环境4.1 配置yum仓库4.2 检查可用yum仓库4.3 安装Docker4.4 检查Docke…

绝区贰--及时优化降低 LLM 成本和延迟

前言 大型语言模型 (LLM) 为各行各业带来了变革性功能&#xff0c;让用户能够利用尖端的自然语言处理技术处理各种应用。然而&#xff0c;这些强大的 AI 系统的便利性是有代价的 — 确实如此。随着 LLM 变得越来越普及&#xff0c;其计算成本和延迟可能会迅速增加&#xff0c;…