贪心算法

目录

  • 1.贪心算法步骤
  • 2.两个关键要素
  • 3.两种背包问题
    3.1 0-1背包问题(适用于动态规划,不满足贪心选择性质)
    3.2 分数背包问题(适用于贪心算法)
  • 4.实例
    4.1 活动选择问题
    4.2 霍夫曼编码
    4.3 最小生成树算法
    参见最小生成树
    4.4 最短路径Dijkstra算法
    参见最短路径专题
    4.5 最小生成树与最短路径问题的比较

1.贪心算法步骤

step1.将最优化问题转换为这样的形式:对其最初一次选择后,只剩下一个子问题需要求解
step2.证明做出贪心选择后,原问题总是存在最优解,即贪心选择总是安全的
step3.证明做出贪心选择后,剩余的子问题满足性质:其最优解与贪心选择组合即可得到原问题的最优解,这样就得到了最优子结构。

2.两个关键要素

1)贪心选择性质
可以通过做出局部最优(贪心)选择来构造全局最优解。

动态规划方法中,每个步骤都要进行一次选择,但选择通常依赖于子问题的解。一般以一种自底向上的方式求解动态规划问题。

贪心算法中,在进行第一次选择之前不求解任何子问题,只是做出当时看来最佳的选择。贪心算法通常是自顶向下的,进行一次又一次选择,将给定问题实例变得更小。

证明每个步骤做出贪心选择能生成全局最优解。这种证明通常首先考察某个子问题的最优解,然后用贪心选择来修改此解,从而得到一个相似的最优解。

2)最优子结构
一个问题的最优解包含其子问题的最优解。
全部证明:将子问题的最优解与贪心选择组合在一起就能生成原问题的最优解。(数学归纳法)

一个问题:贪心选择性质和最优子结构的区别?

贪心算法问题的最优解包括两部分:贪心选择 + 子问题的最优解
a.贪心选择性质针对的是贪心选择部分
b.最优子结构针对的是子问题的最优解
这两个合起来,就构成了贪心问题的最优解,缺一不可

3.两种背包问题

3.1 0-1背包问题(适用于动态规划,不满足贪心选择性质)

3.2 分数背包问题(适用于贪心算法)

4.实例

4.1 活动选择问题



1)最优子结构
Sij表示在ai结束后开始,在aj开始前结束的那些活动的集合;
Aij是Sij的一个最大相互兼容的活动子集
ak属于Aij

求解Aij分解为两个子问题:寻找Sik中的兼容活动,以及寻找Skj中的兼容活动:


证明:


使用c[i,j]表示集合Sij的最优解大小,可得:


2)贪心选择性质(如下定理是基于fi排列顺序而言的)
贪心选择:选择最先结束的活动(或者选择最晚开始的活动)



特别注意:这里构造出来的也是一个最大兼容活动子集,并非是唯一一个!

3)贪心算法


4.2 霍夫曼编码

编码问题:根据字符出现的频率,构造出字符的最优二进制表示,使得压缩率最优。

变长编码:赋予高频字符短字码,赋予低频字符长字码

前缀码:既没有任何字码是其他字码的前缀。前缀码可以简化解码过程。

文件的最优编码方案总是对应一颗满二叉树。若C为字母表且所有字符的出现频率均为正数,则最优前缀码对应树恰有|C|个叶节点,每个叶节点对应字母表中一个字符,且恰有|C| - 1个内部节点。

证明:

对于一颗满二叉树而言:
1)最简单情况:一个根节点+两个叶子,满足情况
2)一颗满二叉树可以由最简单情况重复衍生而来:将一个叶子替换为一个子树(一个根,两个叶子)
    此时叶子增加1(增加两个,减少一个),内部节点增加1(叶子节点转变而来的)

因此,有|C|-1个内部节点,|C|个叶子节点

1)算法代码



2)贪心选择性质(图是象征性的,不是一定的)
关键在于:用贪心选择去修改最优编码树,得到的还是一颗最优编码树


3)最优子结构(反证法,一般用cut-paste方法)


4.3 最小生成树算法

参见最小生成树

4.3.1 最小生成树问题

4.3.2 贪心选择性质

贪心策略:



该算法的理解:
a.集合A总保持无环状态,因为是一棵树;因此对于集合A为安全的边(u, v)所连接的是GA中不同的连通分量;因此,每执行一次循环,减少一棵树
b.算法执行的任意时刻,图GA = (V, A)是一个森林,GA中的每个连通分量是一棵树
算法开始时,集合A为空,森林中包含|V|棵树,每棵树只有一个节点;
c.由a, b可知,while循环总共执行|V| - 1次,当整个森林仅包含一棵树时,终止

循环不变式:
在每次循环之前,A是某棵最小生成树的一个子集。

安全边:满足如下条件的边称之为安全边。
将边(u, v)加入到集合A中,使得A不违反循环不变式,即AU{(u, v)}也是某棵最小生成树的子集。


切割:无向图G=(V, E)的一个切割(S, V-S)是集合V的一个划分
横跨:边(u, v)横跨切割(S, V-S)表示一个端点在集合S,一个在V-S
尊重:如果集合A中不存在横跨该切割的边,则称该切割尊重集合A
轻量级边:在横跨一个切割的所有边中,权重最小的边称为轻量级边

贪心策略中辨认安全边的规则:


一个推论:



一个问题:为什么该切割尊重集合A

根据定义:因为集合A中不存在横跨该切割的边
该切割区分了C,将集合A分为两部分,C和A-C,但是C和A-C并不连通。
所以不存在横跨该切割的一条轻量级边。

4.3.3 最优子结构

如果一个问题的最优解中包含了子问题的最优解,则该问题具有最优子结构。
最小生成树是满足最优子结构的,下面会给出证明:
最优子结构描述:假设我们已经得到了一个图的最小生成树(MST) T,(u, v)是这棵树中的任意一条边。如图所示:


现在我们把这条边移除,就得到了两棵子树T1和T2,
如图:

T1是图G1=(V1, E1)的最小生成树,G1是由T1的顶点导出的图G的子图,E1={(x, y)∈E, x, y ∈V1}
同理可得T2是图G2=(V2, E2)的最小生成树,G2是由T2的顶点导出的图G的子图,E2={(x, y)∈E, x, y ∈V2}
现在我们来证明上述结论:使用剪贴法。w(T)表示T树的权值和。
首先权值关系满足:w(T) = w(u, v)+w(T1)+w(T2)
假设存在一棵树T1'比T1更适合图G1,那么就存在T'={(u,v)}UT1'UT2',那么T'就会比T更适合图G,这与T是最优解相矛盾。得证。

  • 特别注意,上图中(u, v)这条边是连接两棵树的最小边(安全边)

4.3.4 Kruskal算法



4.3.5 Prim算法

该算法的一个简要分析:

初始化:r.key = 0,其余节点u.key = 无穷大
第一次循环:将r从Q中剔除,并更新r的所有邻节点的key
以此类推

4.4 最短路径Dijkstra算法

参见最短路径专题

4.4.1 最短路径问题

4.4.2 最优子结构

4.4.3 Dijkstra算法的适用条件以及贪心选择性质

前提条件:Dijkstra算法解决的是带权重的有向图上单源最短路径问题,该算法要求所有边的权重都为非负值。


算法说明1.松弛操作

1)最短路径的表示(v.Π)
对每个结点,维持一个前驱结点v.Π。该前驱结点可能是另一个结点或者NIL。
设G=(V, E)是一个带权重的有向图,其权重函数为w,假定G不包含从s可以到达的权重为负值的环路,因此,所有的最短路径都有定义。一棵根节点为s的最短路径树是一个有向子图G' = (V', E')


2)松弛操作(v.d)
对于每个结点v,维持一个属性v.d,用来记录从源节点s到结点v的最短路径权重的上界。




松弛操作是唯一导致最短路径估计和前驱结点发生变化的操作。
Dijkstra算法对每条边仅松弛一次。

3)最短路径和松弛操作的一些性质


1.三角不等式
证明:最短路径性质,最短路径是最短的,那必须成立

2.上界性质
证明:归纳法
基础步:显然成立
归纳步:根据归纳假设,松弛前,成立;松弛后,唯一可能发生改变只有v.d
  v.d = u.d + w(u, v) >= δ(s, u) + w(u, v) >= δ(s, v)
因为是下界,所以取到下界肯定不会变化

3.收敛性质
1)根据上界性质,松弛前有u.d = δ(s, u),松弛后仍成立
2)对(u, v)松弛后
   v.d <= u.d + w(u, v)  
        = δ(s, u) + w(u, v)
        = δ(s, v)  (根据最优子结构,前提是s->u->v是一条最短路径)
   根据上界性质,v.d >= δ(s, v),因此有v.d = δ(s, v)

其中为什么进行松弛后v.d <= u.d + w(u, v)?
因为:
a. 如果v.d <= u.d + w(u, v),松弛操作不会改变u.d和v.d的值
b. 如果v.d > u.d + w(u, v),松弛操作后,v.d = u.d + w(u, v)

4.路径松弛性质
使用归纳法,根据收敛性质可以证明

5.前驱子图性质,需要证明三条性质都满足
1)VΠ是从源节点s可以到达的结点的集合
    因为VΠ中的点δ(s, v)都是有限值,因此都可以到达
2)GΠ形成一棵根节点为s的树
a. 首先证明GΠ是无环路的
b. 证明对于属于VΠ的每个结点v,在图GΠ中存在一条从源点s到结点v的唯一简单路径
3)对于所有属于VΠ的结点v,图GΠ中从结点s到结点v的唯一简单路径是图G中从结点s到结点v的一条最短路径。

5-2 GΠ形成一棵根节点为s的树



5-3 对于所有属于VΠ的结点v,图GΠ中从结点s到结点v的唯一简单路径是图G中从结点s到结点v的一条最短路径。
首先搞清楚前驱子图的定义:


证明如下:


算法导论证明是不是有误?
1)对于最优子结构,可以用cut-paste来证明:如果不是G中的最短路径,那么还有一条更短的路径,与v.d = δ(s, d)矛盾
2)对算法道路中的证明稍微修改,将>=号改为=,是否可行?
因为每次松弛后有δ(s, v) = δ(s, u) + w(u, v);
这里有一个特别说明:对于一条简单路径上的结点,因为只有松弛操作才可以改变前驱结点和v.d,所以在GΠ中的边,都有>=;否则不会有松弛操作,因此这里的>=是满足的。

算法说明2.算法的操作
Dijkstra算法在运行过程中维持的关键信息是一组结点集合S。从源节点s到该集合中每个结点之间的最短路径已经被找到。算法重复从结点集V-S中选择最短路径估计最小的结点u,将u加入到集合S,然后对所有从u出发的边进行松弛。
使用一个最小优先队列Q来保存结点集合,每个结点的关键值是其d值。

算法说明3.贪心选择性质的证明



特别说明:

第一次看的时候有一个地方不懂:在将u加入到集合S时,y.d = δ(s, y)
这个是根据收敛性质来的
  • Dijkstra算法的贪心选择性质:
    1)加入集合S的,都有u.d = δ(s, u);此时与S中点相邻的点v都已经被松弛过了。并且s到最小的v必然存在一条最短路径,并且已经被松弛过了,因此v.d=δ(s, v)肯定成立。
    2)为什么s到最小的v存在一条最短路径,而且必然是s~u-v,因为所有的路径是非负的,并且v还未加入到S中,所以任何经过其他路径再到v的路径都要比这条路径长。


4.5 最小生成树与最短路径问题的比较

4.5.1 问题定义的区别

1)最小生成树(带权重无向图)



2)最短路径(带权重有向图;Dijkstra解决的是单源最短路径问题)



4.5.2 Prim和Dijkstra算法

目的不一样:
Prim求的是整个生成树的连接最小,所以一直找最小的边加入
Dijkstra求的是从源点到其他所有点的最短距离,所以要不断relax更新(减小)源点到各个点的距离

1)最小生成树的Prim算法



2)单源最短路径的Dijkstra算法




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

推荐阅读更多精彩内容

  • 贪心算法 当具有最优子结构性质的时候,可以使用动态规划算法也可以使用贪心算法 最优子结构性质、贪心选择性质 虽然贪...
    冰源阅读 1,010评论 0 0
  • 引言:前两天在复习贪心算法时,看到单源最短路径的Dijkstra算法和最小生成树的Prim算法,由于自己不认真,竟...
    cp_insist阅读 7,211评论 1 2
  • 可用贪心算法解决的几个基本问题 关键:看问题有没有贪心选择性质和最优子结构性质。有些问题看似是可以用贪心算法,但是...
    碧影江白阅读 6,184评论 1 2
  • 贪心算法 先来比较一下贪心算法和动态规划 贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择,不考虑整体,...
    Moonsmile阅读 2,758评论 0 1
  • 「个人成长161」梁浩瀚:人性不死,传销不灭 今天是乐于助人会的个人成长日记连载第161篇,我是梁浩瀚,做一个温暖...
    梁浩瀚阅读 154评论 0 0