算法思想 - 贪婪(贪心)算法

贪婪算法

什么是贪婪算法

“贪婪”可以理解为,以逐步的局部最优,达到最终的全局最优。即在每一次选择中都选择当前的最优选择,当选择结束的时候,我们就可以获得全局最优解。(注意,在一定条件下,贪婪策略是正确的,但是在很多情况下,它又是错误的。)

分析贪婪的关键步骤

使用贪婪算法有关键的三步,为了理解方便,这里使用一个例子辅助讲解:

假设我们有一个可以容纳 100kg 物品的背包,可以装下各种物品,现在有 5 种豆子,豆子可以自由拆分和搭配,豆子的总量和总价值如下图。请问如何装豆子才能让背包中的物品的总价值最大?
贪心-豆子理解.jpg

你可以先自己思考该怎么解决这个问题,然后我们再看如何用贪婪的思想来解决这个问题:

1.当我们看到这类问题,首先要联想到贪婪算法:对一组数据,我们定义了限制值和期望值,希望从中选出几个数据,在满足限制值的情况下,期望值最大。
在刚才的例子中,限制值->背包承重100kg,期望值->物品总价值最大,数据-> 5 种豆子的价值和总量。

2.尝试使用贪心算法解决问题:根据贪心策略,每次选择在当前情况下,对限制值同等贡献量的情况下,对期望值贡献最大的数据。
在例子中,就是选择单价最高的豆子。

3.验证贪心策略下的结果是否最优。在大部分情况下,只需要举几个例子就可以很方便地验证。

无法使用贪婪的情况

实际上,使用贪心算法解决问题的思路,并不总是能够给出最优解。一下面的例子为例,我们要找一条从 S 到 T 的最短路径:
贪心失效.jpg

使用贪心策略的结果是:S->A->E->T,路径长度为 9 。
而最短路径为:S->B->D->T,路径长度为 6 。

在这个例子中,贪心算法失效的主要原因是,前面的选择会影响之后的选择。你也可以从贪心的思想入手:在很多情况下,局部最优并不一定是全局最优

在生活中我们也经常会遇到这样的情况:一个人在人生的每一个岔路口都做出了当时最好的选择,他在每一次争斗中都胜利了,但是他的一生却并并不如意。我常常将这种事当做悲剧,薛宝钗在一定程度上是这样的人,二战中的日本走的道路也是这样。最终,薛宝钗并未如愿,日本也走向了深渊。(关于这个问题,你可以去听听《冬吴相对论》的第100期:合成谬误的陷阱)

贪心算法的例子

下面给出几个可以使用贪心策略解决的问题的例子:

1.分糖果
我们有 m 个糖果和 n 个孩子。我们现在要把糖果分给这些孩子吃,但是糖果少,孩子多(m<n),所以糖果只能分配给一部分孩子。
每个糖果的大小不等,这 m 个糖果的大小分别是 s1,s2,s3,……,sm。除此之外,每个孩子对糖果大小的需求也是不一样的,只有糖果的大小大于等于孩子的对糖果大小的需求的时候,孩子才得到满足。假设这 n 个孩子对糖果大小的需求分别是 g1,g2,g3,……,gn。
问题:如何分配糖果,能尽可能满足最多数量的孩子?

分析如下:
限制值:只有 m 个糖果
期望值:满足的孩子最多
数据:孩子的需求 Si 和 糖果的大小 Gi
贪心策略:使用尽量小的糖果满足最容易满足的孩子
具体行为:在未被满足的孩子中,需找对糖果需求最小的,然后给他糖果中能满足他的最小糖果。

2.钱币找零
这个问题在我们的日常生活中更加普遍。假设我们有 1 元、2 元、5 元、10 元、20 元、50 元、100 元这些面额的纸币,它们的张数分别是 c1、c2、c5、c10、c20、c50、c100。我们现在要用这些钱来支付 K 元,最少要用多少张纸币呢?

限制值:找零的面额
期望值:最少的纸币张数
数据:所有纸币的面额
贪心策略:优先使用最大面值
具体行为:你可以自己试试

注意,在现实生活中,RMB的找零可以用贪婪算法解决。但是钱币找零的问题并不能用贪婪解决所有情况。比如我们有三种纸币:100,99,1,现在要 198 元,最优解为 2 个 99 元。而贪婪算法会给出 1 个 100 元 和 98 个 1 元。

3.区间覆盖
假设我们有 n 个区间,区间的起始端点和结束端点分别是[l1, r1],[l2, r2],[l3, r3],……,[ln, rn]。我们从这 n 个区间中选出一部分区间,这部分区间满足两两不相交(端点相交的情况不算相交),最多能选出多少个区间呢?

贪心-区间.jpg

限制值:指定的区间,例如[l1,rn]
期望值:最多的不相交区间
数据:所有区间范围
贪心策略:选择最小范围的不重叠的区间
具体行为:看下图


贪心-区间选择.jpg

经典应用:霍夫曼(哈夫曼)编码

贪婪算法最经典的应用,就是使用霍夫曼编码的方法对数据进行压缩,我们看下面的例子:

假设我有一个包含 1000 个字符的文件,每个字符占 1 个 byte(1byte=8bits),存储这 1000 个字符就一共需要 8000bits,那有没有更加节省空间的存储方式呢?

假设我们通过统计分析发现,这 1000 个字符中只包含 6 种不同字符,假设它们分别是 a、b、c、d、e、f。而 3 个二进制位(bit)就可以表示 8 个不同的字符,所以,为了尽量减少存储空间,每个字符我们用 3 个二进制位来表示。那存储这 1000 个字符只需要 3000bits 就可以了,比原来的存储方式节省了很多空间。不过,还有没有更加节省空间的存储方式呢?

这时候,霍夫曼编码就要登场了,霍夫曼编码不仅会考察文本出现的所有字符集,还会统计文本中字符出现的频率,根据出现的频率,我们给出霍夫曼的编码:
哈夫曼-压缩编码.jpg

上面是霍夫曼编码,由于 a~f 的频率依次递减,所以以人的思维看来,它的编码过程非常简单。但是如何实现一个通用的构造编码的过程呢?这里需要构建哈夫曼树

我们把每个字符看作一个节点,并且辅带着把频率放到优先级队列中。我们从队列中取出频率最小的两个节点 A、B,然后新建一个节点 C,把频率设置为两个节点的频率之和,并把这个新节点 C 作为节点 A、B 的父节点。最后再把 C 节点放入到优先级队列中。重复这个过程,直到队列中没有数据。
哈夫曼-构建哈夫曼树.jpg

现在,我们给每一条边加上画一个权值,指向左子节点的边我们统统标记为 0,指向右子节点的边,我们统统标记为 1,那从根节点到叶节点的路径就是叶节点对应字符的霍夫曼编码。
哈夫曼树-哈夫曼编码.jpg

以上就是贪心算法的全部内容

注:本文章的主要内容来自我对极客时间app的《数据结构与算法之美》专栏的总结,我使用了大量的原文、代码和截图,如果想要了解具体内容,可以前往极客时间

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353