首页 > 编程语言 >贪心算法

贪心算法

时间:2023-03-29 19:13:19浏览次数:37  
标签:算法 数组 区间 思路 最优 摄像头 贪心

贪心和动态规划的区别

  1. 有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿? 【贪心】
    -- 指定每次拿最大的,最终结果就是拿走最大数额的钱。(每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优)
  2. 有一堆盒子,你有一个背包体积为n,如何把背包尽可能装满?
    -- 如果还每次选最大的盒子,就不行了。这时候就需要动态规划

贪心的套路

  • 通过局部最优,推出整体最优
  • 靠自己手动模拟,如果模拟可行,就可以试一试贪心策略,如果不可行,可能需要动态规划。
  • 举反例,如果想不到反例,那么就试一试贪心吧
  • 贪心有时候就是常识性的推导,所以会认为本应该就这么做

贪心的解题步骤

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

贪心的题目

1. 分发饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;
每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。
你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
【思路】为了满足更多的小孩,就不要造成饼干尺寸的浪费。大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子,那么就应该优先满足胃口大的。这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。

  • 先将饼干数组和小孩数组排序。
  • 从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计满足小孩数量

2. 摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。
给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。
【思路】需要画图

  • 局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰
  • 整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。
    让峰值尽可能的保持峰值,然后删除单一坡度上的节点
    另外要考虑特殊情况
  • 上下坡中有平坡
  • 数组首尾两端
  • 单调坡度有平坡

3. 最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
【思路】如果 -2 1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心贪的地方!

  • 局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
  • 全局最优:选取最大“连续和”

4. 买卖股票的最佳时机II

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易
【思路】这道题目可能我们只会想,选一个低的买入,再选个高的卖,再选一个低的买入.....循环反复
其实最终利润是可以分解的。假如第0天买入,第3天卖出,那么利润为:prices[3] - prices[0]。
相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。此时就是把利润分解为每天为单位的维度,而不是从0天到第3天整体去考虑

  • 局部最优:收集每天的正利润
  • 全局最优:求得最大利润。

5. 跳跃游戏

给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个位置。
【思路】其实跳几步无所谓,关键在于可跳的覆盖范围,那么这个问题就转化为跳跃覆盖范围究竟可不可以覆盖到终点!
每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。

  • 贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围)
  • 整体最优解:最后得到整体最大覆盖范围,看是否能到终点。

6. 跳跃游戏II

给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。你的目标是使用最少的跳跃次数到达数组的最后一个位置。
【思路】本题要计算最小步数,那么就要想清楚什么时候步数才一定要加一

  • 局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一
  • 整体最优:一步尽可能多走,从而达到最小步数。
    从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最小步数。
    这里需要统计两个覆盖范围,当前这一步的最大覆盖和下一步最大覆盖。

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

给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)以这种方式修改数组后,返回数组可能的最大和。
【思路】

  • 局部最优:让绝对值大的负数变为正数,当前数值达到最大
  • 整体最优:整个数组和达到最大。
    解决步骤:
    第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
    第二步:从前向后遍历,遇到负数将其变为正数,同时K--
    第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
    第四步:求和

8. 加油站

在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
【思路】
1.可以双层循环,使用暴力看是否能得到一个解
2. 使用贪心,分析思路如下:

  • 局部最优:当前累加rest[i]的和curSum一旦小于0,起始位置至少要是i+1,因为从i之前开始一定不行
  • 全局最优:找到可以跑一圈的起始位置
    首先如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明 各个站点的加油站 剩油量rest[i]相加一定是大于等于零的。每个加油站的剩余量rest[i]为gas[i] - cost[i],i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油。起始位置从i+1算起,再从0计算curSum

9. 分发糖果

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。
每个孩子至少分配到 1 个糖果。相邻的孩子中,评分高的孩子必须获得更多的糖果。
【思路】这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,如果两边一起考虑一定会顾此失彼。
先确定右边评分大于左边的情况(也就是从前向后遍历):

  • 局部最优:只要右边评分比左边大,右边的孩子就多一个糖果
  • 全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果
    再确定左孩子大于右孩子的情况(从后向前遍历)
  • 局部最优:取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,保证第i个小孩的糖果数量既大于左边的也大于右边的
  • 全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。

10. 柠檬水找零

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。
注意,一开始你手头没有任何零钱。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
【思路】只需要维护三种金额的数量,5,10和20。有三种情况:
情况一:账单是5,直接收下。
情况二:账单是10,消耗一个5,增加一个10
情况三:账单是20,优先消耗一个10和一个5,如果不够,再消耗三个5

  • 局部最优:遇到账单20,优先消耗美元10,完成本次找零
  • 全局最优:完成全部账单的找零

11. 根据身高重建队列

假设有打乱顺序的一群人站成一个队列,数组 people
people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人
请你返回正确顺序的数组 people 所表示的队列
【思路】首先需要根据体重排序,找到其对应的顺序,再更具k值将人放在对应的位置
遇到两个维度权衡的时候,一定要先确定一个维度,再确定另一个维度。
按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。

  • 局部最优:优先按身高高的people的k来插入。插入操作过后的people满足队列属性
  • 全局最优:最后都做完插入操作,整个队列满足题目队列属性

12. 用最少数量的箭引爆气球

给你一个数组 points ,其中 points [i] = [xstart,xend] ,弓箭可以从x轴垂直出发,返回引爆所有气球所必须射出的最小弓箭数。
【思路】只射重叠最多的气球,用的弓箭一定最少

  • 局部最优:当气球出现重叠,一起射,所用弓箭最少
  • 全局最优:把所有气球射爆所用弓箭最少。
    为了让气球尽可能的重叠,需要对数组进行排序,如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭。
这里其实是需要代码功底的,那代码功底怎么练?
多看多写多总结!

13. 无重叠区间

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
【思路】让区间尽可能的重叠。按照右边界排序,从左向右记录非交叉区间的个数。最后用区间总数减去非交叉区间的个数就是需要移除的区间个数了。

14. 划分字母区间

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
【思路】要求同一字母最多出现在一个片段中,那么如何把同一个字母的都圈在同一个区间里呢?
在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。

  • 统计每一个字符最后出现的位置
  • 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点
    【其他转换思路】统计字符串中所有字符的起始和结束位置,记录这些区间(实际上也就是无重叠区间题目里的输入),将区间按左边界从小到大排序,找到边界将区间划分成组,互不重叠。找到的边界就是答案。

15. 合并区间

给出一个区间的集合,请合并所有重叠的区间。
【思路】先排序,让所有的相邻区间尽可能的重叠在一起,按左边界,或者右边界排序都可以,处理逻辑稍有不同。

  • 按照左边界从小到大排序之后,如果 intervals[i][0] <= intervals[i - 1][1] 即intervals[i]的左边界 <= intervals[i - 1]的右边界,则一定有重叠
  • 合并区间:用左边界和右边界作为合并后的区间

16. 单调递增的数字

给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。
【思路】

  • 98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]--,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。
  • 从后向前遍历,就可以重复利用上次比较得出的结果了,从后向前遍历332的数值变化为:332 -> 329 -> 299

17. 监控二叉树

给定一个二叉树,我们在树的节点上安装摄像头。节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。计算监控树的所有节点所需的最小摄像头数量。
【思路】首先要想,如何放置,才能让摄像头最小的呢?

  • 从题目中示例,其实可以得到启发,我们发现题目示例中的摄像头都没有放在叶子节点上!(摄像头可以覆盖上中下三层,如果把摄像头放在叶子节点上,就浪费的一层的覆盖。)
  • 头结点放不放摄像头也就省下一个摄像头, 叶子节点放不放摄像头省下了的摄像头数量是指数阶别的。所以从叶子节点开始看。
  • 局部最优:让叶子节点的父节点安摄像头,所用摄像头最少
  • 整体最优:全部摄像头数量所用最少!

标签:算法,数组,区间,思路,最优,摄像头,贪心
From: https://www.cnblogs.com/xiaoyu-jane/p/17270015.html

相关文章

  • 【算法】笔记
    初心:最开始出发的原因论文的代码复现也就是算法及其实现,需要精通算法学习完算法的基础知识,大致了解什么是算法以及有哪些算法目标拆分采用28法则分析事物的本质,......
  • 分布式技术原理与算法解析 04 - 存储&高可靠
    分布式存储分布式数据复制技术常用于数据备份同步复制技术注重一致性,用户请求更新数据库时,主数据库要同步到备数据库后才结束阻塞返回给用户异步复制技术注重可用......
  • 基于注水算法的MIMO信道容量matlab仿真
    1.算法描述MIMO无线通信技术源于天线分集与智能天线技术,具有二者的优越性,MIMO系统的发射端与接收端都采用多天线单元,MIMO系统具有抑制干扰、抗多径衰落等特征。使用MIMO技......
  • 基于注水算法的MIMO信道容量matlab仿真
    1.算法描述      MIMO无线通信技术源于天线分集与智能天线技术,具有二者的优越性,MIMO系统的发射端与接收端都采用多天线单元,MIMO系统具有抑制干扰、抗多径衰落等特征......
  • m基于C3D-hog-GRNN广义回归神经网络模型的人员异常行为识别算法的matlab仿真
    1.算法描述      实时的人群异常行为识别是一项极具挑战的工作,具有较高的现实意义和社会需求,快速准确地判断出异常行为并及时预警,一直是我们探索的方向。传统的机器......
  • matlab代码:基于麻雀搜索算法的无线传感器网络3D-Dvhop定位算法
    matlab代码:基于麻雀搜索算法的无线传感器网络3D-Dvhop定位算法-在三维空间中,利用麻雀搜索算法寻找未知节点到锚节点的实际距离和估计距离之间的最小误差,完成对未知节点位......
  • Matlab 车辆配送路径规划问题 四大算法解决旅行商问题(TSP) CVRP CDVRP VRPTW
    Matlab车辆配送路径规划问题四大算法解决旅行商问题(TSP) CVRPCDVRPVRPTWtsp:旅行商问题,寻找最短闭合路径cvrp:带容量约束的车辆路径规划dvrp:带距离约束的车辆路......
  • 粒子群算法储能容量优化配置,有三篇参考
    粒子群算法储能容量优化配置,有三篇参考。物有所值关键词:储能优化配置粒子群 储能充放电优化主要内容:建立了储能的成本模型,包含运行维护成本以及容量配置成本,然后以......
  • CF(2D) (树上贪心)
      思路:关键性质是赋值是由跟到某个点,然后权值是不减序列从叶子节点进行回推,由于是不减序列,而且为了然后父亲节点能够白嫖,于是让儿子节点的权值尽量大就行了,......
  • Brian Kernighan's 算法
    介绍BrianKernighan's算法是一种用于计算一个整数的二进制表示中有多少个1的高效算法。该算法的基本思想是每次将该整数的最右边的一个1置为0,直到该整数变为0为止。每次......