当前位置: 首页 > news >正文

2.贪心算法.基础

2.贪心算法.基础

  • 基础知识
  • 题目
    • 1.分发饼干
    • 2.摆动序列
      • 2.1.思路二:动态规划法
    • 3.最大子序和
    • 4.买股票的最佳时机2
      • 4.1.思路二:动态规划法
      • 4.2.买股票的最佳时机
    • 5.跳跃游戏
      • 5.1.跳跃游戏2
    • 6.K次取反后最大化的数组和
    • 7.加油站
    • 8.分发糖果
  • 总结

基础知识

什么是贪心? 贪心的本质是选择每一阶段的局部最优,从而达到全局最优。
贪心的套路
贪心算法并没有固定的套路。不好意思,也没有! 靠自己手动模拟,如果模拟可行,就可以试一试贪心策略,如果不可行,可能需要动态规划。那如何验证可不可用贪心算法?最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧
一般的数学证明有如下两种方法:
1.数学归纳法
2.反证法

面试中基本不会让面试者现场证明贪心的合理性,代码写出来跑过测试用例即可,或者自己能自圆其说理由就行了。
贪心一般解题步骤,一般分为如下四步:
1.将问题分解为若干个子问题
2.找出适合的贪心策略
3.求解每一个子问题的最优解
4.将局部最优解堆成全局最优解
做题的时候,只要想清楚 局部最优 是什么,如果推导出全局最优,其实就够了。

贪心没有套路,说白了就是常识性推导加上举反例。贪心的一般解题步骤,大家可以发现这个解题步骤也是比较抽象的,不像是二叉树,回溯算法,给出了那么具体的解题套路和模板。

题目

1.分发饼干

(题目链接)
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
在这里插入图片描述
为了不浪费饼干的尺寸,打算尽量用尺寸最大的饼去给胃口最大的孩子,以此往下推,每一步充分发挥这个当前饼尺寸的作用。

    int findContentChildren(vector<int>& g, vector<int>& s) {std::sort(g.begin(), g.end());std::sort(s.begin(), s.end());int index=0; // for personfor(int i=0; i<s.size(); i++){ // for cakeif(index<g.size() && g[index]<=s[i]) index++;}return index;}

for循环可以从饼开始匹配,从人开始匹配,但要主要方向的不同


2.摆动序列

(题目链接)
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。例如, [1,7,4,9,2,5] 是一个摆动序列,而[1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列。
因此题目要求是 给定一个整数序列,返回作为摆动序列的最长子序列的长度
这是思路是:局部最优——除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值;整体最优——整个序列有最多的局部峰值,从而达到最长摆动序列。
实际操作上,其实连删除的操作都不用做,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)
在这里插入图片描述
要处理一下三种特殊情况,结合题目要求情况一的结果应该是3;情况二的结果应该是2;情况三的结果应该是2,因为单调种的平坡不能算是峰值。那如何如何消除这些平坡的影响呢?因为摆动是通过prediffcurdiff的符号变化来添加峰值计数,我们只要让prediff在发生摆动时,才修改就行了,对于平坡的情况,pre的符号就维持不变。

    int wiggleMaxLength(vector<int>& nums) {if(nums.size()<=1) return nums.size();int curdiff = 0;int prediff = 0;int res = 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)){res++;prediff = curdiff;}}return res;}

时间复杂度:O(n^2);空间复杂度:O(n)

2.1.思路二:动态规划法


3.最大子序和

(题目链接)
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和
暴力解法:通过两层for循环,完成整数数组的子集和的统计,最后比较得出最大的值即可。
其时间复杂度:O(n^2);空间复杂度:O(1)

贪心解法:局部最优——最大连续和的,设置另外一个数组存放原本数组上从0开始连续和>0的数值,当连续和<0时,则从下一个数值开始计数。最后得到这个连续
在这里插入图片描述

    int maxSubArray(vector<int>& nums) {int res = INT_MIN;int count = 0;for(int i=0; i<nums.size(); i++){count += nums[i];if(count>res) res = count;if(count<0) count=0;}return res;}

这里res初始化为INT_MIN是为了处理当数组首个字母是负数的情况;


4.买股票的最佳时机2

(题目链接)
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格:计算你所能获取的最大利润(但注意你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票))。
例如:输入: [7,1,5,3,6,4]:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

思路:1.想要获取利润,至少两天为一个交易单元 2.初始想法是选择一个低价买入,再高价卖出…一直这样循环 3.

    int maxProfit(vector<int>& prices) {int res = 0;for(int i=1; i<prices.size(); i++){res += max(prices[i]-prices[i-1], 0);}return res;} 

4.1.思路二:动态规划法

4.2.买股票的最佳时机

(题目链接)
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子卖出该股票。设计一个算法来计算你所能获取的最大利润。只有一个购买-卖出的周期,也就是一次获取利润的机会。

    int maxProfit(vector<int>& prices) {int res = 0;int min_pri = INT_MAX;for(int i=0; i<prices.size(); i++){min_pri = prices[i]<min_pri? prices[i]:min_pri;res = res<prices[i]-min_pri? prices[i]-min_pri: res;}return res;}

5.跳跃游戏

(题目链接)
给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false

    bool canJump(vector<int>& nums) {int cover = 0;if(nums.size()==1) return true;for(int i=0; i<=cover; i++){cover = max(i+nums[i], cover);if(cover >= nums.size()-1) return true;}return false;}

5.1.跳跃游戏2

(题目链接)
给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:目标是使用最少的跳跃次数,并返回该次数。
在这里插入图片描述
与上一题不同,该题要求最小步数,因此需要设置两个变量存储当前步可覆盖范围,下一步可覆盖范围:循环特点是 没进入一层cover时,会更新precover值,并与之前的precover比较覆盖;当cover=curcover时,步数统计count+1,且将precover值赋给curcover;最后当precover覆盖数组末尾时退出。

    int jump(vector<int>& nums) {if(nums.size()==1) return 0;// 两者初始化从0出发int curcover = 0;int precovner = 0;int count = 0;for(int i=0; i<nums.size(); i++){//实时计算在下一步可到达的范围precovner = max(i + nums[i], precovner);if(i==curcover){count++;curcover = precovner; //转化为当前步可到达的范围if(precovner>=nums.size()-1) break;}}return count;

6.K次取反后最大化的数组和

(题目链接)
给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。重复这个过程恰好 k 次。可以多次选择同一个下标 i 。以这种方式修改数组后,返回数组 可能的最大和 。
基本思路是1.将数组中的负数尽量反转为正数 2.若剩余数组均为正数,此时所剩k值若为奇数,则选择一个值最小的正数反转为负数, 若剩余k值是偶数,则无影响。

	// 加了绝对值排序法int largestSumAfterKNegations(vector<int>& nums, int k) {std::sort(nums.begin(), nums.end(), cmp);for(int i=0; i<nums.size(); i++){if(nums[i]<0 && k>0){nums[i] *= -1;k--;}}if(k%2 == 1) nums[nums.size()-1] *= -1;int res = 0;for(int n:nums) res += n;return res;}//正常递增序列排序法int largestSumAfterKNegations(vector<int>& nums, int k) {std::sort(nums.begin(), nums.end());int min_abs = 0;for(int i=0; i<nums.size(); i++){if(nums[i]<0 && k>0){nums[i] *= -1;k--;}min_abs = abs(nums[min_abs])<abs(nums[i])? min_abs: i;}if(k%2==1) nums[min_abs] *= -1;int res=0;for(int n:nums) res += n;return res;}

7.加油站

(题目链接)
在这里插入图片描述
暴力的方法很明显就是O(n^2)的,遍历每一个加油站为起点的情况,模拟一圈。

贪心算法1:情况一若gas总和小于cost总和,则一定跑不完一圈;情况二,从0开始出发,累计一圈下来,若中途累加值<0,则说明从0出发不可行;情况三,此时京start后移,即start从尾部朝头部移动,若该节点和能使之前中途累加值的负值填平,则可以从该节点出发。
贪心算法2:当局部连续数组和<0时,说明在i步遇到较大的负值,到时总和不满足,此时可以判断从i之前开始一定不可行(理解这个判断:说明从start到i-1步及之前是满足>0约束的,若存在start~i之间的一个值index到i值的区间满足>0,则说明在start到index区间的值<0,这不符合假设。),至少从i+1开始。

	// 贪心1:最少满足start延后int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int cursum = 0;int min = INT_MAX;for(int i=0; i<gas.size(); i++){int res = gas[i]-cost[i];cursum += res;if(cursum<min){min = cursum;}}if(cursum<0) return -1;if(min>=0) return 0;for(int i=gas.size()-1; i>0; i--){int res = gas[i]-cost[i];min += res;if(min>=0) return i;}return -1;}// 贪心2:最长局部累加和int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int cursum = 0;int totalsum = 0;int start = 0;for(int i=0; i<gas.size(); i++){cursum += gas[i] - cost[i];totalsum += gas[i] - cost[i];if(cursum<0){start = i+1;cursum = 0;}}if (totalsum<0) return -1;return start;}

时间复杂度:O(n);空间复杂度:O(1)


8.分发糖果

(题目链接)
这道题目有点意思 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。你需要按照以下要求,给这些孩子分发糖果:
1.每个孩子至少分配到 1 个糖果。 2.相邻两个孩子评分更高的孩子会获得更多的糖果。请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目
确定左孩子比右孩子大的情况一定是从后面往前遍历,否则不能利用右边孩子的candy的比较情况,得到vec1;确定右孩子比左孩子大的情况是从前往后遍历,这样也是未来利用左孩子的candy的比较情况,得到vec2;最后取candy的vector时,取vec1,vec2各个索引位置上candy的max情况——这样即满足了右孩子比左孩子大,左孩子比右孩子大的情况。

    int candy(vector<int>& ratings) {std::vector<int> candyvec(ratings.size(), 1);for(int i=1; i<ratings.size(); i++){if(ratings[i]>ratings[i-1]) candyvec[i] = candyvec[i-1]+1;}for(int i=ratings.size()-2; i>=0; i--){if(ratings[i]>ratings[i+1]) candyvec[i] = max(candyvec[i+1]+1, candyvec[i]);}int res = 0;for(int n:candyvec) res += n;return res;}

总结

相关文章:

2.贪心算法.基础

2.贪心算法.基础 基础知识题目1.分发饼干2.摆动序列2.1.思路二&#xff1a;动态规划法 3.最大子序和4.买股票的最佳时机24.1.思路二&#xff1a;动态规划法4.2.买股票的最佳时机 5.跳跃游戏5.1.跳跃游戏2 6.K次取反后最大化的数组和7.加油站8.分发糖果 总结 基础知识 什么是贪…...

用Python轻松转换PDF为CSV

数据的可访问性和可操作性是数据管理的核心要素。PDF格式因其跨平台兼容性和版面固定性&#xff0c;在文档分享和打印方面表现出色&#xff0c;尤其适用于报表、调查结果等数据的存储。然而&#xff0c;PDF的非结构化特性限制了其在数据分析领域的应用。相比之下&#xff0c;CS…...

关于微信支付-商户平台:查询订单提示“查询失败:操作失败,请稍候重试”的分析

目录 引子 分析 应对 小结 引子 在开发和实施微信 JSAPI 支付的应用后&#xff0c;我们遇到了一些问题&#xff0c;订单的状态更新不正常&#xff0c;当然我们首先需要从自身寻找原因和完善解决问题的办法和方案。在支付的过程中&#xff0c;客户会给我们一些反馈&#xf…...

掌握【Python异常处理】:打造健壮代码的现代编程指南

目录 ​编辑 1. 什么是异常&#xff1f; 知识点 示例 小李的理解 2. 常见的内置异常类型 知识点 示例 小李的理解 3. 异常机制的意义 知识点 示例 小李的理解 4. 如何处理异常 知识点 示例 小李的理解 5. 抛出异常 知识点 示例 小李的理解 6. Python内置…...

STM32点灯闪烁

stm32c8t6引脚图 开发板引脚图 GPIO端口的每个位可以由软件分别配置成 多种模式。 ─ 输入浮空 ─ 输入上拉 ─ 输入下拉 ─ 模拟输入 ─ 开漏输出 ─ 推挽式输出 ─ 推挽式复用功能 ─ 开漏复用功能 配置GPIO端口步骤&#xff1a;开启时钟->使用结构体设置输出模式…...

Java-01-源码篇-04集合-05-SortedMap NavigableMap TreeMap

目录 一&#xff0c;SortedMap 二&#xff0c;NavigableMap 三&#xff0c;TreeMap 3.1 TreeMap 继承结构 3.2 TreeMap 属性 3.3 TreeMap 构造器 3.4 TreeMap 内部类 3.4.1 Values 3.4.2 KeySet 3.4.3 EntrySet 3.4.5 相关集合迭代器 3.4.5.1 PrivateEntryIterato…...

拥抱 AGI:PieDataCS 引领云原生数据计算系统新范式

自2023年后&#xff0c;人工智能技术进入了一个更为成熟和广泛应用的阶段&#xff0c;人工通用智能&#xff08;AGI&#xff09;这一概念也成为了科技界和产业界热议的焦点。本文将结合 AGI 时代背景&#xff0c;从架构设计到落地实践&#xff0c;详细介绍拓数派云原生数据计算…...

开放式耳机哪个品牌好?开放式耳机推荐

开放式耳机因其独特的设计&#xff0c;提供了更自然的听音体验和更好的环境声音感知&#xff0c;尤其适合长时间佩戴和户外运动使用&#xff0c;下面来推荐几款表现出色的开放式耳机&#xff1a; 悠律ringbuds pro凝声环&#xff08;499元&#xff09;&#xff1a;凭借时尚潮流…...

kubernetes dashboard安装

1.查看符合自己版本的kubernetes Dashboard 比如我使用的是1.23.0版本 https://github.com/kubernetes/dashboard/releases?page5 对应版本 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.1/aio/deploy/recommended.yaml修改对应的yaml,…...

【MySQL】3.表的操作

表的操作 一.创建表二.查看表三.修改表四.删除表 一.创建表 create table [if not exists] tb_name( field1 datatype comment 说明, field2 datatype, field3 datatype) charsetutf8 collateutf8_gerenal_ci engineInnoDB//表的编码集&#xff0c;校验集如果不指定&#xff…...

十一、作业

1.从大到小输出 写代码将三个整数数按从大到小输出。 void Swap(int* px, int* py) {int tmp *px;*px *py;*py tmp;} int main() {int a 0;int b 0;int c 0;scanf("%d %d %d", &a, &b, &c);int n 0;if (a<b){Swap(&a, &b);}if (a &l…...

关于C#在WPF中如何使用“抽屉”控件

关于C#在WPF中如何使用“抽屉”控件 1.前提准备2.XAML代码3.对应的C#代码4.显示效果 1.前提准备 需要引用MaterialDesign控件库&#xff0c;关于如何引用&#xff0c;请参照文章——关于C#如何引用MaterialDesign控件库 2.XAML代码 <Window x:Class"MaterialDesign_…...

运维Tips | Ubuntu 24.04 安装配置 xrdp 远程桌面服务

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] Ubuntu 24.04 Desktop 安装配置 xrdp 远程桌面服务 描述&#xff1a;Xrdp是一个微软远程桌面协议&#xff08;RDP&#xff09;的开源实现&#xff0c;它允许我们通过图形界面控制远程系统。这里使…...

ExcelVBA运用Excel的【条件格式】(二)

ExcelVBA运用Excel的【条件格式】&#xff08;二&#xff09; 前面知识点回顾 1. 访问 FormatConditions 集合 Range.FormatConditions 2. 添加条件格式 FormatConditions.Add 方法 语法 表达式。添加 (类型、 运算符、 Expression1、 Expression2) 3. 修改或删除条件…...

肠道和大脑中犬尿氨酸代谢途径的紊乱

新出现的证据表明&#xff0c;肠道微生物群可能与宿主大脑相互作用&#xff0c;并在神经精神疾病的发病机制中发挥关键作用。然而&#xff0c;抑郁症中微生物-肠-脑轴相互作用的潜在机制仍不清楚。在这项研究中&#xff0c;建立了慢性约束应激 (CRS) 的小鼠模型&#xff0c;以研…...

vue通过后台返回的数字显示不同的文字内容,多个内容用、隔开

后台返回的数据 显示效果&#xff1a; html&#xff1a; <el-table-columnalign"center"label"使用过的小程序"width"124"v-if"activeTab 0"><template #default"scope"><divv-for"(item, index) in s…...

Flume工具详解

Flume是一个由Apache提供的开源日志收集系统&#xff0c;最初由Cloudera贡献。它以其高可用性、高可靠性和分布式特性而著称&#xff0c;被广泛应用于海量日志的采集、聚合和传输。以下是对Flume工具的详细解析&#xff1a; 一、概述 功能定位&#xff1a;Flume主要用于收集、…...

vulhub-activemq(CVE-2016-3088)

在 Apache ActiveMQ 5.12.x~5.13.x 版本中&#xff0c;默认关闭了 fileserver 这个应用&#xff08;不过&#xff0c;可以在conf/jetty.xml 中开启&#xff09;&#xff1b;在 5.14.0 版本后&#xff0c;彻底删除了 fileserver 应用。【所以在渗透测试过程中要确定好 ActiveMQ …...

上海市计算机学会竞赛平台2024年6月月赛丙组超级奇数

题目描述 如果一个十进制数的所有数字都是奇数&#xff0c;则称之为超级奇数&#xff0c;例如 35733573 就是一个超级奇数&#xff0c;而 3141531415 不是。按照从小到大排序&#xff0c;前几名的超级奇数为 1,3,5,7,9,11,13,15,17,⋯1,3,5,7,9,11,13,15,17,⋯ 给定一个超级…...

速盾:cdn业务优化

CDN&#xff08;Content Delivery Network&#xff09;是一种基于互联网的分布式网络架构&#xff0c;旨在提供更快速、可靠的内容传输服务。它通过将内容分发至多个节点&#xff0c;使用户可以从离他们更近的节点获取内容&#xff0c;从而提高访问速度和用户体验。 然而&…...

重生奇迹mu的地图名

地图之一&#xff1a;勇者大陆 勇者大陆地处奇迹大陆中央。终年阴雨连绵&#xff0c;气候潮湿闷热。植物由充满黑暗阴森气氛的草地所构成。这里的NPC数量是所有地图中最多的。因为地步交通要冲&#xff0c;所以也是玩家聚集最多的地方。 这里是剑士、魔法师、魔剑士和圣导师初…...

【CSS】缩写属性gap

在CSS Grid Layout&#xff08;网格布局&#xff09;和Flexbox&#xff08;弹性盒布局&#xff09;中&#xff0c;gap 是一个缩写属性&#xff0c;用于同时设置行间隙&#xff08;gutter&#xff09;和列间隙&#xff08;在Flexbox中通常称为“交叉轴间隙”&#xff09;的大小。…...

Perl 语言开发(八):子程序和模块

目录 1. 引言 2. 子程序的基本概念与用法 2.1 子程序的定义和调用 2.2 传递参数 2.3 返回值 2.4 上下文和返回值 3. 模块的基本概念与用法 3.1 模块的定义 3.2 使用模块 3.3 导出符号 3.4 模块的文件结构和命名 4. 实际应用中的子程序与模块 4.1 子程序参数验证与…...

自注意力机制和多头注意力机制区别

Ref&#xff1a;小白看得懂的 Transformer (图解) Ref&#xff1a;一文彻底搞懂 Transformer&#xff08;图解手撕&#xff09; 多头注意力机制&#xff08;Multi-Head Attention&#xff09;和自注意力机制&#xff08;Self-Attention&#xff09;是现代深度学习模型&#x…...

数据结构第14节 加权图

加权图是在图论中一种更为复杂的图结构&#xff0c;它扩展了无向图和有向图的概念&#xff0c;通过给图中的边附加一个数值来表示边的某种属性&#xff0c;如成本、距离、容量或相似度等。这个数值被称为边的“权重”。 定义 加权图可以被形式化地定义为一个三元组 ( G (V, …...

128陷阱(超详细)

int x 128;int y 128;int n 127;int m 127;Integer d Integer.valueOf(x);Integer g Integer.valueOf(y);Integer z Integer.valueOf(n);Integer v Integer.valueOf(m);System.out.println(d g);System.out.println(z v); 思考一下他的结果是什么&#xff1f; 为什么…...

STM32自己从零开始实操08:STM32主控原理图

由于老师使用的各引脚分门别类的单片机原理图我没有找到&#xff0c;我使用是引脚按顺序摆放的&#xff0c;不方便一个模块一个模块截图展示&#xff0c;所以这部分使用老师的原理图。 一、电源 1.1电源的介绍 1.1.1数字电源和地&#xff08;VDD和VSS&#xff09; 数字电源…...

Ubuntu20.04配置TurtleBot3 Waffle Pi远程控制

这里写目录标题 0. 机器人配置1. Ubuntu20.04配置TurtleBot3 Waffle Pi远程控制1.1 TurtleBot3 Waffle Pi端配置1.2 PC端配置1.2.1 安装turtlebot3的环境配置1.2.2 创建项目并安装Turtlebot31.2.3 配置环境变量 1.3 PC端与TurtleBot3进行通信1.3.1 PC端与机器人端互PING和SSH连…...

SaaS产品和独立部署型产品有什么区别,该怎么选择?

随着云计算和软件服务的多样化&#xff0c;产品形式主要划分SaaS型&#xff08;开通即用&#xff09;和独立部署&#xff08;完整交付&#xff09;两种模式&#xff0c;那么SaaS产品和独立部署产品有哪些区别&#xff0c;我们在选择产品的时候应该如何去抉择&#xff1f;本文我…...

【Linux】压缩命令——gzip,bzip2,xz

1.压缩文件的用途与技术 你是否有过文件太大&#xff0c;导致无法以正常的E-mail方式发送&#xff1f;又或学校、厂商要求使用CD或DVD来做数据归档之用&#xff0c;但是你的单一文件却都比这些传统的一次性存储媒介还要大&#xff0c;那怎么分成多块来刻录&#xff1f;还有&am…...