转自:奶糖猫

贪心算法概念叙述

运用贪心算法求解问题时,会将问题分为若干个子问题,可以将其想象成俄罗斯套娃,利用贪心的原则从内向外依次求出当前子问题的最优解,也就是该算法不会直接从整体考虑问题,而是想要达到局部最优。只有内部的子问题求得最优解,才能继续解决包含该子问题的下一个子问题,所以前一个子问题的最优解会是下一个子问题最优解的一部分,重复这个操作直到堆叠出该问题的最优解。

贪心算法最关键的部分在于贪心策略的选择,贪心选择的意思是对于所求问题的整体最优解可以通过一系列的局部最优选择求得。而必须注意的是,贪心选择必须具备无后效性,也就是某个状态不会影响之前求得的局部最优解。

运动贪心算法解决相应问题时会比较简单和高效,省去了寻找全局最优解很多不必要的穷举操作,由于贪心算法问题并没有固定的贪心策略,所以唯一的难点就是找到带求解问题的贪心策略,但毕竟熟能生巧嘛,算法的基本思想总是固定不变的。

贪心算法求解步骤

  1. 将问题分解为若干个子问题

  2. 找出适合的贪心策略

  3. 求解每一个子问题的最优解

  4. 将局部最优解堆叠成全局最优解

下面通过利用贪心算法解决四道LeetCode题目,加深一下对贪心算法思想的掌握,其中第一道为easy,其余三道为medium,会标注出相应的题号。

来源:力扣(LeetCode)链接:https://leetcode-cn.com

455.分发饼干

问题描述:假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

注意:

  • 你可以假设胃口值为正。

  • 一个小朋友最多只能拥有一块饼干

这道题的思路主要包括两个点:

  1. 尽量先满足胃口值小的孩子,因为这样的孩子容易满足。

  2. 进行条件1时,尽可能选用尺寸小的,这样大尺寸饼干可以用来满足胃口值大的孩子。

这道题的贪心思想非常明显,就是要尽可能地满足更多的孩子,而胃口值小的孩子是容易满足的,反之胃口值大的孩子很难满足,所以在抉择上尽可能满足前者、饿着后者。

这个思想可以类比于赛马,我们假设赢或者平作为满足条件。如果A的3赢了B的1,那么剩下两匹的结果可能就是一平一负或者两负,那么此时至多才是1满足;而如果A的马和B的马都按照顺序比,则可以达到3平,那么此时可以达到3满足。

所以综上可以得到解题思路,首先需要将胃口值和饼干尺寸由小至大排序。设定一个计数器child,用来记得到满足的孩子个数,再维护一个饼干指针cookies。如果饼干尺寸可以满足孩子胃口值,即g[child]<=s[cookies],就将child、cookies分别加一(向后移动一位),否则只将cookies向后移动一位。因为孩子的胃口值是由小到大的,若不满足当前的胃口值更不会满足之后的。


时间复杂度:两次排序加一次循环,如果选择时间复杂度较优的排序方法,那么。

55. 跳跃游戏

题目描述:给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个位置。

首先明确一下解题目标,若要能够到达最后一个位置,那么就需要最后一跳的最大距离加上该位置下标一定要大于等于数组长度,即nums[i]+i>=length(nums),而当前元素又一定处于之前元素最远可以达到范围之内,这样层层嵌套不就是贪心算法思想中的子问题的形式嘛。

我们要从数组的第一个元素开始遍历,并且维护一个最远可以到达的位置(max_i),当遍历到数组中的某一个位置i时,如果i在max_i范围之内,并且此时最远可以达到位置大于max_i,那么就通过i+nums[i]更新max_i,如果在遍历过程中max_i大于等于数组长度,则代表可以达到最后一个位置,反之不能。要注意的是,max_i既不是数组下标也不是数组中某个元素,而是二者的加和。

拿上面两个示例为例:

  • 示例1:最开始下标为0的元素值为2,此时max_i=2,所以下标1、2都在max_i之内,当达到下标1时,此时max_i = 1+3 = 4,所以可以达到最后一个位置。

  • 示例2:最开始下标为0的元素值为3,此时max_i=3,下标1、2、3在范围内,但在遍历这三个位置时会发现max_i=2+1=1+2=0+3总是等于3,而3<4,所以最后一个位置永远达不到。

时间复杂度:,一层循环。

435.无重叠区间

题目描述:给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

注意:

  1. 可以认为区间的终点总是大于它的起点。

  2. 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。

本题的要求是“找到需要移出区间的最小数量”,换句话说就是要更多地保留集合中的区间,那么对于有重叠的区间,就应该尽可能删去跨度较大的区间。

这里我们根据区间的终点进行贪心选择,不是说起点不行,而是终点更好,那原因呢?因为如果每次选择的区间结尾越小,留给后面区间的空间自然就变多了,那么后面能留下的区间数量也就越多。用一句话概括就是每次都选择终点最小的,因为这一定是最优解的一部分,这不就是正是贪心思想的应用嘛。

解这道题时需要先将数组按照区间的终点进行排序,然后需要维护一个end指针,它代表当前集合中的最小终点,在遍历数组时,若当前元素的起点大于前一区间的终点,那么不重叠区间的计数器加一,更新end指针;反之则不做任何操作,最后区间总数减去不重叠区间即为需要移除区间的最小数量。

时间复杂度:一次排序加一次循环,。

LeetCode中第452题:用最少数量的箭引爆气球与本题解法十分相似,大家可以类比本题的思路自己练习。

376. 摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。

例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

给定一个整数序列,返回作为摆动序列的最长子序列的长度。通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。

示例1和示例3比较特殊,一个是完全摆动序列,另一个是完全升序序列,所以这里利用比较普通的示例2讲解,依据示例2中的数组可以大致绘制出一个元素分布图,如下:

其中橙色点就构成了一个摆动序列,所以橙色点的个数也是最终要输出的结果。可以看到[5,10,13,15]是一个连续递增的子序列,5处于17之后是符合题意的,所以一定将其保留,而对于[10,13,15]三个元素,只有保留15才可以形成摆动序列。

所以对于一段连续递增的子序列,只有保留这段子序列的首尾元素时,才能形成一个摆动序列,并且这也加大了尾部的后一个元素成为摆动序列的下一个元素的可能性。同理连续递减的子序列也做如上操作,比如图中的[15,10,5]。

解决这道题的关键就在于如何保留连续连续递增的子序列首尾元素,结合栈是一个很好的方法,但出栈入栈的条件是什么呢?我们维护一个状态值nowstate,他共有"up"和"down"两种取值,"up"表示该元素大于前一个元素,"dowm"表示该元素小于前一个元素。

从第二个元素开始遍历数组,因为第一个元素(下标为0)一定处于摆动序列内。若当前元素大于前一个元素且nowstate="up",这就说明连续递增出现了,就需要从栈移除前一个元素。反之将nowstate更新为"up",因为此时前一个nowstate="down",另一种可能性同理。不论什么条件下都要做入栈操作,因为这里只靠条件过滤不符合的元素。


时间复杂度:,一层循环。

总结

从上面几道题中不难看出只要依据题意找出相应的贪心策略,解题就十分容易,并且代码也不复杂,但贪心选择的方法并不唯一,主要还是靠对算法的理解和解题的经验。贪心算法和动态规划是原理有些相似的两种算法,同一问题利用不同算法解题的思路、难易程度各不相同,不要相互混淆。

上期推文:

LeetCode刷题实战1:在数组上遍历出花样

LeetCode刷题实战2:用链表模拟加法

LeetCode刷题实战3:最长不重复子串

LeetCode刷题实战4:两个正序数组的中位数

LeetCode刷题实战5:判断回文子串

LeetCode刷题实战6:Z字形变换

LeetCode刷题实战7:整数反转

LeetCode刷题实战8:字符串转换整数

LeetCode刷题实战9:求解回文数

LeetCode刷题实战10:字符串正则匹配

LeetCode刷题实战11: 盛最多水的容器

LeetCode刷题实战12: 整数转罗马数字

LeetCode刷题实战13: 罗马数字转整数

LeetCode刷题实战14: 最长公共前缀

LeetCode刷题实战15:三数之和

LeetCode刷题实战16: 最接近的三数之和

LeetCode刷题实战17: 电话号码的字母组合

LeetCode刷题实战18: 四数之和

LeetCode刷题实战19:删除链表的倒数第N个节点

LeetCode刷题实战20:有效括号

LeetCode刷题实战21:合并两个有序链表

LeetCode刷题实战22:括号生成

LeetCode刷题实战23:合并K个升序链表

总结 贪心算法_用经典例题轻松帮你搞定贪心算法相关推荐

  1. 如何删除Word页眉下横线?只需1招即可轻松帮你搞定!

    在我们职场办公时候经常会处理各种Word文档,这时候总会遇到各种类型的问题,就比如页眉下讨人厌的横线,经常为这个莫名其妙的横线而感到头疼,关键它还删除不掉! 针对这个问题,特意为大家整理了几个小技巧, ...

  2. word一键排版工具_超赞的Word标尺小工具,轻松帮你搞定各种「对不齐」排版问题...

    排版一直对不齐?图片点击居中了却没有真的居中?表格始终无法居中对齐? 猜你的Word文档还在使用空格控制缩进,其实最标准最快捷的办法是利用标尺,以上的问题都可以轻松解决. 标尺是啥?相信不熟悉WORD ...

  3. layui 表格数据源_「WPS办公助手」表格数据录入太慢?这个好用的技巧,轻松帮你搞定...

    日常使用表格时,常常会需要「数据查找录入」,虽然看似简单,但操作起来并不方便. 比如说下方表格中,右侧的信息对应表,需要在左侧的人员信息表查找并录入对应的数据,要怎么做呢? 肯定会有人觉得:就这么点数 ...

  4. 如何重新设置苹果id密码_苹果手机ID密码忘了?别着急,这二种方法轻松帮你搞定!...

    苹果手机ID密码相信大家都并不陌生,一般使用苹果手机时候每个人都会有个ID账号以及ID密码.当我们下载APP时候等等都会使用需要ID密码进行验证身份,但是如果有一天当我们忘记ID密码咋办呢? 大家不用 ...

  5. 会议纪要手写太麻烦,手机在线语音转文字,轻松帮你搞定

    最近经常有朋友问我怎么才能快速的进行语音转文字,因为每次开会的时候都因为会议记录没做好被老板批评,但是每次会议记录都是手写或者电脑码字,速度远远跟不上领导说话的速度,其实用手机就可以帮你快速的完成会议 ...

  6. mp3格式怎么转换?这3种方法轻松帮你搞定!

    随着互联网时代的发展,音频格式也逐渐呈现多样化,不再局限于mp3格式.然而由于音频格式的不断增加,与播放器不兼容的情况也时有发生.这个问题该如何解决呢?其实我们只需借助一些音频软件把音频转换成mp3格 ...

  7. lora发射和接收原理_四个要点,帮你搞定LoRa天线匹配电路

    四.天线安装规范 在所有硬件参数调整好后,天线的安装也是关键一步,天线辐射是有方向性的,并不是每个方向辐射相等的能量,如同我们讲话一样,有的方向听到的声音强,有的方向弱.安装天线的时候,需要将天线辐射 ...

  8. dos 退出for循环_循环?一次帮你搞定!

    循环 循环在代码世界的重要性不言而喻,今天我来说一下几种循环代码的组成方式,以及选择最适合你的方式. 想象一下你是个农夫考虑一下你的晚饭如何准备,这就是一个循环. 循环通常具有一个或者多个条件: 开始 ...

  9. 4大Excel文本合并技巧,这几个公式轻松帮你搞定

    有时我们在制作Excel表格时,对Excel文本进行合并是常事,那你掌握了多少了,若是还不会对Excel文本 进行合并,那就来看看小编给大家分享的这六个Excel合并技巧公式. 在输入公式的时候,我们 ...

最新文章

  1. 2022-2028年中国PET薄膜行业市场深度分析及未来趋势预测报告
  2. ant-design-pro Login 中的 UserName 和 Password 的验证规则 rules
  3. Linux last命令后面的时间
  4. python恶搞小程序-知道了这个,你也能写出 Python 趣味小程序
  5. linux路由修改密码,Linux中修改Mysql root用户密码的方法
  6. Linux文件系统及属性
  7. 74 岁的柳传志和 34 岁的联想
  8. 关于layui中lay-verify=required无效的解决办法
  9. linux删除编译中间件,关于linux 里安装编译环境和中间件
  10. JAVA 读取txt文件内容
  11. XP SP3多数功能借鉴Vista 安装将无需密码
  12. VB基础知识之Do...Loop循环
  13. ansible中变量注册 register的使用
  14. android平台的oa系统架构,基于Android的移动OA办公系统的设计与实现
  15. rac多scan-ip配置
  16. 计算机网络的权威杂志,科学网—晒个自己整理的计算机网络和通信方向可能相关的期刊列表...
  17. excel录制宏运行规划求解不能运行的问题
  18. 魔兽争霸英雄属性全揭秘
  19. OpenStack 企业私有云的若干需求(7):电信行业解决方案 NFV
  20. 网站推广----献给广大站长(转载)

热门文章

  1. ios 如何获得系统时间和日期
  2. java获取linux下面所有线程,获取Linux中Java线程的线程ID
  3. OJ1160: 矩阵的最大值(指针专题)(C语言)
  4. OJ1078: a+b(多实例测试1)(C语言数组解题)
  5. 信息学奥赛一本通(1165:Hermite多项式)
  6. 青蛙的约会(POJ-1061)
  7. C++ 语言基础 —— STL —— 算法 —— 二分查找算法
  8. 图论 —— 图的连通性
  9. 信息学奥赛C++语言:找第一个只出现一次的字符
  10. 信息学奥赛C++语言:切蛋糕