《趣学算法(第2版)》读书笔记 Part 3 :贪心算法基础(理论)

14天阅读挑战赛


系列笔记链接

《趣学算法(第2版)》读书笔记 Part 1 :如何高效学习算法

《趣学算法(第2版)》读书笔记 Part 2 :算法入门

《趣学算法(第2版)》读书笔记 Part 3 :贪心算法基础(理论)

《趣学算法(第2版)》读书笔记 Part 4 :贪心算法基础(操作)


贪心算法基础(理论)

对应图书2.1章节内容。



贪心本质

《算法导论》:

贪心算法是“活在当下,看清楚眼前”的方法。贪心算法从问题的初始解开始,一步一步地做出当前最好的选择,逐步逼近问题的目标,尽可能地得到最优解,即使达不到最优解,也可以得到最优解的近似解。

贪心算法在解决问题的策略上“目光短浅”。只根据当前信息就做出选择,且一旦做出选择,不管将来有什么结果,这个选择都不会改变。即,贪心算法并不是从整体最优考虑,它所做出点选择只是在某种意义上的局部最优。在实际应用中,很多问题都可以通过贪心算法得到最优解或最优解的近似解。

在贪心算法中,需要注意以下几个问题

  1. 一旦做出选择,不可以回溯。
  2. 有可能得不到最优解,而是最优解的近似解。
  3. 选择什么样的贪心策略,直接决定了算法的好坏。

2.1.2 贪亦有道

贪心算法需要遵循的原则。

“君子爱财,取之有道”,在贪心算法中“贪亦有道”。

在遇到具体问题时,人们往往分不清哪些问题能用贪心算法求解,哪些问题不能使用贪心算法。但经过实践发现,利用贪心算法求解答问题往往具有两个重要的性质:贪心选择最优子结构。只要满足这两个性质就可以使用贪心算法。

  1. 贪心选择
    贪心选择,是指原问题的整体最优解可以通过一系列局部最优的选择得到。
    先做出当前最优的选择,将原问题变为一个相似的但规模更小的子问题,而后的每一步都是当前最优的选择。这种选择依赖于已做出的选择,但不依赖于未做出的选择。

  2. 最优子结构
    最优子结构,是指原问题的最优解包含子问题的最优解。
    当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构是该问题是否可用贪心算法求解的关键。
    贪心算法通过一系列的局部最优解(子问题的最优解)得到全局最优解(原问题的最优解),如果原问题的最优解和子问题的最优解没有关系,则求解子问题没有任何意义,就无法采用贪心算法。
    例如,对于原问题 S = S= S={ a 1 , a 2 , … , a i , … , a n a_1,a_2,…,a_i,…,a_n a1a2aian} ,可通过贪心选择选出一个当前最优解 { a i a_i ai} 之后,转换为求解子问题 S − S- S{ a i a_i ai} ,继续求解该子问题,最后对所有子问题的最优解进行合并,即可得到原问题的最优解。

2.1.3 贪心算法秘籍

贪心算法秘籍

  1. 贪心策略
    首先要确定贪心策略,选择当前看上去最好的那个方案。
    以挑选苹果为例,如果求解目标是苹果越大越好,那每次就从苹果堆中拿一个最大的苹果,作为局部最优解,贪心策略就是选择当前最大的苹果;如果求解目标是苹果越红越好,那每次就从苹果堆中拿一个最红的苹果,贪心策略就是选择当前最红的苹果。综上所述,根据求解目标不同,贪心策略也会不同。

  2. 求解过程
    根据贪心策略,一步一步地得到局部最优解。
    例如,首先选一个最大的苹果记为a1;然后从剩下的苹果堆中选择一个最大的苹果记为 { a 2 a_2 a2} ,以此类推。最后,合并所有的局部最优解,即可得到原问题的最优解 { a 1 , a 2 , … a_1,a_2,… a1a2} 。

补充

换个视角看贪心算法

参考资料:

贪心算法 Greedy Algorithme
详解贪心算法(Python实现)
贪心算法及实例
贪心算法九题详解


Leetcode对贪心算法的释义

Leetcode中的贪心算法分栏共有278道题目。
题目难度分三个级别:简单、中等、困难,其中简单级别共35题。

Leetcode对贪心算法的释义

贪心算法,又称贪婪算法,指在对问题求解时,总是做出在当前看来是最好的选择,就能得到问题的答案。贪心算法需要充分挖掘题目中条件,没有固定的模式,解决有贪心算法需要一定的直觉和经验。

贪心算法不是对所有问题都能得到整体最优解:

  • 能使用贪心算法解决的问题具有「贪心选择性质」。
    「贪心选择性质」严格意义上需要数学证明。
  • 能使用贪心算法解决的问题必须具备「无后效性」。
    即某个状态以前的过程不会影响以后的状态,只与当前状态有关。


Leetcode 题目示例(仅题目)


2160. 拆分数位后四位数字的最小和(难度:简单 通过率:85.2%

给你一个四位 整数 num
请你使用 num 中的 数位 ,将 num 拆成两个新的整数 new1new2
new1new2 中可以有 前导 0 ,且 num 中 所有 数位都必须使用。

比方说,给你 num = 2932 ,你拥有的数位包括:两个 2 ,一个 9 和一个 3
一些可能的 [new1, new2] 数对为 [22, 93][23, 92][223, 9][2, 329]
请你返回可以得到的 new1new2最小 和。

示例 1:

输入:num = 2932
输出:52
解释:可行的 [new1, new2] 数对为 [29, 23][223, 9] 等等。
最小和为数对 [29, 23] 的和:29 + 23 = 52

示例 2:

输入:num = 4009
输出:13
解释:可行的 [new1, new2] 数对为 [0, 49][490, 0] 等等。
最小和为数对 [4, 9] 的和:4 + 9 = 13

提示:

1000 <= num <= 9999


1221. 分割平衡字符串(难度:简单 通过率:84.7%

在一个 平衡字符串 中,'L''R' 字符的数量是相同的。
给你一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串。
注意:分割得到的每个字符串都必须是平衡字符串,且分割得到的平衡字符串是原平衡字符串的连续子串。
返回可以通过分割得到的平衡字符串的 最大数量

示例 1:

输入:s = "RLRRLLRLRL"
输出:4
解释:s 可以分割为 "RL""RRLL""RL""RL" ,每个子字符串中都包含相同数量的 'L''R'

示例 2:

输入:s = "RLLLLRRRLR"
输出:3
解释:s 可以分割为 "RL""LLLRRR""LR" ,每个子字符串中都包含相同数量的 'L''R'

示例 3:

输入:s = "LLLLRRRR"
输出:1
解释:s 只能保持原样 "LLLLRRRR".

示例 4:

输入:s = "RLRRRLLRLL"
输出:2
解释:s 可以分割为 "RL""RRRLLRLL" ,每个子字符串中都包含相同数量的 'L''R'

提示:

  • 1 <= s.length <= 1000
  • s[i] = 'L' 或 'R'
  • s 是一个 平衡 字符串

大佬营友们的笔记

  1. 破晓之翼 https://ghdata.blog.csdn.net/article/details/127484441
  2. 疯狂抓头 http://t.csdn.cn/W9rvY
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰.封万里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值