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

贪心算法理论基础

选取每一阶段的局部最优,堆叠成全局最优。遇到求最优解问题时,可以先手动模拟一下,将问题分解,举例分析小问题的局部最优是否能达到全部最优,能的话就可以试一下贪心算法。贪心算法的题没有固定的套路和判别方法,基本就是靠常识和手动模拟的方式。
其实算法书中有数学推导,但在面试刷题中用不着。

分发饼干

Alt
用大饼干满足胃口大的小孩,小饼干满足胃口小的小孩,尽量不造成饼干的浪费
对每一个小孩找合适的饼干是可以的,但这既需要遍历小孩也需要遍历饼干。我们可以对小孩的胃口从大到小进行 for 循环,用另一个指针指向最大的饼干,每当匹配上才移动指针,指向次大的饼干。
也可以对饼干从小到大进行 for 循环,用另一个指针指向胃口最小的小孩,满足当前小孩就向后移动指针,指向胃口第二小的小孩。

class Solution{
public:int findContentChildren(vector<int>& g, vector<int>& s){sort(s.begin(), s.end());sort(g.begin(), g.end());int index = s.size() - 1;  // 指针指向最大的饼干int result = 0;for(int i = g.size() - 1; i >= 0; i--){// 从胃口最大的小孩开始,按小孩胃口次序匹配最合适的饼干if(index >= 0 && s[index] >= g[i]){index--;result++;}}return result;}
};

另一种写法

class Solution{
public:int findContentChildren(vector<int>& g, vector<int>& s){sort(s.begin(), s.end());sort(g.begin(), g.end());int result = 0;int index = 0;  // 指向胃口最小的小孩for(int i = 0; i < s.size(); i++){if(index < g.size() && s[i] >= g[index]){  // 如果当前的最小饼干满足了小孩,就去找下一个小孩index++;result++;}}return result;}
};

摆动序列

Alt

贪心解法

要从原数组中选择出一个大一个小的序列,只需要删除单调坡上的元素。局部最优就是删除单调坡上除了两个端点以外的中间点,就可以得到两个峰值;全局最优就是峰值点最多的序列,组成最长的摆动序列。贪心体现在我们在遍历时尽量让摆动元素选在局部峰值位置。
那就设计到如何判断一个点是否是局部峰值点,主要是平坡情况带来的干扰。分为以下三种情况:

  1. 上下坡中间是平坡
  2. 数组首尾有平坡
  3. 单调坡中间有平坡
class Solution{
public:int wiggleMaxLength(vector<int>& nums){if(nums.size() == 1)  return 1;int preDiff = 0;  // 上两个元素之间的差初始化为0int curDiff = 0;int result = 1;  // 数组最后一个元素是一个峰值for(int i = 0; i < nums.size() - 1; i++){curDiff = nums[i + 1] - nums[i];  // 求下一个元素与当前元素的差// 将等于0丢给preDiff,这样可以覆盖平坡中的情况1和情况2,总是取平坡的最后一个元素作为峰值if((preDiff >= 0 && curDiff < 0) || (preDiff <= 0 && curDiff > 0)){// 当前元素满足局部峰值条件result++;preDiff = curDiff;  // 因为我们只是判断差值的符号,不需要准确的记录差值,所以只在峰值更新时更新差值,以覆盖平坡中的情况3,不然会把单调坡中的平坡元素记录下来}}return result;}
};

动态规划思路

如何选定一个元素加入摆动序列,它要么被拿来当山峰,要么当做山谷。dp[i][0]表示以元素 i 结尾的摆动序列的最长长度,其中元素i 被当做山峰;dp[i][1]表示以元素 i 结尾的摆动序列的最长长度,其中元素i 被当做山谷。
那么状态转移方程为:
dp[i][0] = max(dp[i][0], dp[j][1] + 1), 0 < j < i && nums[j] < nums[i],将元素 i 接在以 j 为山谷的元素后面。反之亦然。

class Solution{
public:int wiggleMaxLength(vector<int>& nums){int dp[1000][2];memset(dp, 0, sizeof dp);dp[0][0] = dp[0][1] = 1;  // 以当前元素结尾的摆动序列,当前序列做山峰for(int i = 1; i < nums.size(); i++){dp[i][0] = dp[i][1] = 1;for(int j = 0; j < i; j++){if(nums[i] > nums[j]){dp[i][0] = max(dp[i][0], dp[j][1] + 1);}if(nums[i] < nums[j]){dp[i][1] = max(dp[i][1], dp[j][0] + 1); }}}return max(dp[nums.size() - 1][0], dp[nums.size() - 1][1]);}
};

最大子序和

Alt

贪心思路

贪心并不好想,像是[-2,1]这样的数组,我们肯定倾向于选择1。如果当前子数组的和已经为负数,那么这部分和对后续序列只能带来负向的影响。所以贪心的策略就是如果局部序列加和为负,就抛弃该序列,从头开始计算总和,这样会得到很多序列的局部最优,求各个序列的局部最优的最大值,就可以获得全局最优。

class Solution{
public:int maxSubArray(vector<int>& nums){int count = 0;  // 计算局部序列和int result = INT_MIN;  // 更新目前出现的和的最大值for(int i = 0; i < nums.size(); i++){count += nums[i];if(count > result){result = count;  // 在求局部最优的过程就更新全局最优的值}if(count < 0){count = 0;  // 当前的序列和已经小于0,重新记录总和}}return result;}
};

动态规划思路

这个比较好想,当前序列的和一定是与上一个序列是相关的。设dp[i]表示以元素 i 为结尾的序列的最大和,可以得到转移方程dp[i] = max(dp[i - 1] + nums[i], nums[i]),要么重新记和,要么加上之前的序列,取最大值。

class Solution{
public:int maxSubArray(vector<int>& nums){vector<int> dp(nums.size(), 0);dp[0] = nums[0];int result = dp[0];for(int i = 1; i < nums.size(); i++){dp[i] = max(dp[i - 1] + nums[i], nums[i]);if(dp[i] > result)  result = dp[i];}return result;}
};

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

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

相关文章

个体诊所电子处方系统设计,社区门诊处方开单管理系统软件教程

个体诊所电子处方系统设计&#xff0c;社区门诊处方开单管理系统软件教程 一、前言 以下软件程序操作教程以 佳易王诊所电子处方管理系统软件V17.3为例说明 如图&#xff0c;在基本信息设置里&#xff0c;可以设置处方配方模板&#xff0c;这样在开电子处方的时候可以一键导入…

MYSQL表的约束详解!

文章目录 前言一、空属性二、默认值三、列描述四、zerofill五、主键六、自增长七、唯一键八、外键 前言 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据…

【服务器】关于lspci指令查看网卡数量的小坑

准备用lspci指令查看服务器上有多少个网卡&#xff0c;但是由于对lspci的输出结果不了解&#xff0c;导致得到了错误的结果&#xff0c;折腾了好几周 T_T 一、什么是lspci指令&#xff1f;如何使用&#xff1f; 1、lspci指令用来查看当前系统连接的所有PCI/PCIe设备 2、使用…

单元测试——题目十二

目录 题目要求: 定义类 测试类 题目要求: 根据下列流程图编写程序实现相应处理,执行j=10*x-y返回文字“j1=:”和计算值,执行j=(x-y)*(10⁵%7)返回文字“j2=:”和计算值,执行j=y*log(x+10)返回文字“j3=:”和计算值。 编写程序代码,使用JUnit框架编写测试类对编写的…

Android读写文件,适配Q以上

Android Q升级了文件系统&#xff0c;访问文件不仅仅是说动态权限了&#xff0c;有各种限制。权限什么的就不赘述了&#xff0c;下面介绍一下在10以上的系统中访问文件。 首先是打开文件管理器 /*** 打开文件管理器 存储卡和外接U盘都可以访问*/public void openFileManager()…

太阳能 LED 恒流电源 升降压原理图 AP9193 大功率升压恒流IC

特别 宽输入电压范围&#xff1a;3.6V~100V 高效率&#xff1a;可高达 95% 工作频率&#xff1a;1MHz CS 限流保护电压&#xff1a;250mV FB 电流采样电压&#xff1a;250mV 芯片供电欠压保护&#xff1a;2.5V 关断时间可调 外置频率补偿脚 应用领域 LED 灯杯 电池供…

203.移除链表元素(力扣LeetCode)

文章目录 203.移除链表元素题目描述原链表删除元素虚拟头节点 203.移除链表元素 题目描述 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head …

Navicat 16 for MySQL:打造高效数据库开发管理工具

随着数据的快速增长和复杂性的提升&#xff0c;数据库成为了现代应用开发中不可或缺的一部分。而在MySQL数据库领域&#xff0c;Navicat 16 for MySQL作为一款强大的数据库开发管理工具&#xff0c;正受到越来越多开发者的青睐。 Navicat 16 for MySQL拥有丰富的功能和直观的界…

Pygame之纯Python实现你好2024效果

Pygame之纯Python实现你好2024效果 前言&#xff1a; 对于某些指JavaScript与前端实现为Python实现你好2024效果的营销号实在看不下去了。无底线营销&#xff0c;还要私信拿源码&#xff0c;hhh 于是就有了以下代码&#xff1a; 运行前安装pygame pip install pygame运行效果…

鸿蒙系统的APP开发

鸿蒙系统&#xff08;HarmonyOS&#xff09;是由华为公司开发的一款分布式操作系统。它被设计用于在各种设备上实现无缝的、统一的用户体验&#xff0c;包括智能手机、平板电脑、智能电视、智能穿戴等设备。鸿蒙系统的核心理念是支持多终端协同工作&#xff0c;使应用能够更灵活…

Vulnhub-dc5

靶场下载 https://download.vulnhub.com/dc/DC-5.zip 信息收集 # nmap -sn 192.168.1.0/24 -oN live.port Starting Nmap 7.94 ( https://nmap.org ) at 2024-01-21 20:56 CST Nmap scan report for 192.168.1.1 (192.168.1.1) Host is up (0.00057s latency). MAC Address:…

『建议收藏』OpenAI官方出的Prompt提示词教程中文版来了!

一些结论 六大策略: 写清晰的指令 提供参考文本 将复杂任务分解为更简单的子任务 给模型时间“思考” 使用外部工具 系统性测试变化 提高结果质量的六大策略 写清晰的指令 这些模型无法读懂你的想法。如果输出过长&#xff0c;要求简短回复&#xff1b;如果输出过于简单…

STM32(更新中)

目录 1 时钟&#xff08;心跳&#xff09; 1.1 CubeMX基本配置 1.2 外设在时钟上的分配原理 1.3 时钟树 2 寄存器&#xff08;地址&#xff09; 3 GPIO 3.1 GPIO实物 3.2 GPIO两种结构&#xff08;推挽/开漏&#xff09; 3.3 LED 3.4 CUBEMX 3.5 常用函数 …

Redis常见数据类型[上]

目录 前言&#xff1a; 基本全局命令 KEYS EXISTS DEL EXPIRE TTL TYPE 数据结构和内部编码 内部编码&#xff1a; 单线程架构 引出单线程模型&#xff1a; 为什么单线程还这么快&#xff1f; String字符串 字符串数据类型&#xff1a; 常见命令&#xff1a; S…

计算机网络-编制与调制(基带信号 基带传输 宽度信号 宽度传输 编码 调制 )

文章目录 基带信号与宽带信号编码与调制数字数据编码为数字信号数字数据调制为模拟信号模拟数据编码为数字信号模拟数据调制为模拟信号小结 基带信号与宽带信号 信道上传输的信号除了可以分为数字信号和模拟信号&#xff0c;也可以分为基带信号和宽带信号&#xff0c;只是分类…

文心一言 VS 讯飞星火 VS chatgpt (188)-- 算法导论14.1 5题

五、用go语言&#xff0c;给定 n 个元素的顺序统计树中的一个元素 x 和一个自然数 i &#xff0c;如何在O(lgn)的时间内确定工在该树线性序中的第 i 个后继&#xff1f; 文心一言&#xff0c;代码正常运行&#xff1a; 在顺序统计树&#xff08;也称为平衡二叉搜索树&#xf…

2. HarmonyOS 应用开发 DevEco Studio 准备-2

2. HarmonyOS 应用开发 DevEco Studio 准备-2 首选项设置 中文设置 主题 字体 插件安装和使用 保存时操作 编辑器 工程树管理 代码树管理 标记 字符串可视化编辑 参考文档 常用快捷键 编辑 查找或替换 编译与运行 调试 其他 预览 页面预览 自定义组件预览 预览…

[设计模式Java实现附plantuml源码~创建型] 复杂对象的组装与创建——建造者模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

linux中配置文件目录为什么用etc来命名

在早期的 Unix 系统中&#xff0c;/etc 目录的名称确实来源于单词 “etcetera” 的缩写&#xff0c;最初意味着 “其他”&#xff0c;用来存放杂项或者不属于其他特定目录的文件。然而&#xff0c;随着时间的推移&#xff0c;/etc 目录的用途逐渐演变并专门化。 在现代的 Linux…

数据监控-Prometheus/Grafana

一、数据监控Prometheus 1、什么是Prometheus Prometheus是由SoundCloud开源监控告警解决方案,从2012年开始编写代码,到2015年github上开源以来,吸引不少用户以及公司的使用。Prometheus作为新一代的开源解决方案,很多理念与Google SRE的运维之道不谋而合。 2、Promet…