【算法导论】学习笔记——第16章 贪心算法
貪心算法是使做出的選擇看起來都是當前最佳的,期望通過所做的局部最優選擇來產生一個全局最優解。其實,這個定義旨在說明貪心算法必須伴隨做出最優選擇,如moving table,我們選擇最大重疊數等等。當然,很多情況下,并不一定局部最優解就是全局最優解。與DP類似,很多貪心算法設計時都很容易想到遞歸的形式,然而由于深度太深,很容易stack overflow。因此,這時候,大多我們都需要將遞歸變為遞推。以前,不是很會轉化。現在,覺得很容易。遞歸是自頂向下求解,而遞推則是自底向上求解。一般遞推都需要伴隨著表來實現。
1. 在開發一個貪心算法時,我們一般要遵循如下幾個步驟:
(1)設計問題的最優子結構
(2)設計出一個遞歸解
(3)證明在遞歸的任一階段,最優選擇之一總是貪心選擇。那么,做貪心選擇總是安全的
(4)設計出一個實現貪心策略的遞歸算法
(5)將遞歸算法轉換成迭代算法(即將遞歸轉化為遞推)
通過這些步驟,可以看出動態規劃與貪心很類似。其實很多問題都看似可以貪心,實則無法滿足最優解的條件,只能DP。正如作者所說,在構造貪心時,我們可以會直接作出貪心選擇,很多時候,貪心選擇很明顯且易構造。對我而言,難點往往是證明貪心的合理性。
2. 貪心選擇性質
貪心選擇性質是貪心算法的關鍵點之一,一個全局最優解可以通過局部最優(貪心)選擇來實現,才滿足貪心條件。也就是說,當考慮做出選擇時,我們總是基于當前情況做出最優選擇,我們認為通過當前最優選擇可以獲得全局最優解。而在動態規劃中,當前的選擇與之前的選擇很可能相關,動態規劃在這一點上更類似于一個狀態機進行狀態轉移,逐漸轉移到最優狀態,但在當前某一步并不一定是當前的最優狀態。很多時候可以通過對數列排序等對子問題進行選擇,從而降低問題復雜度。
3. 最優子結構
對于一個問題來說,如果它的一個最優解包含了其子問題的最優解,則稱該問題具有最優子結構。在貪心算法中使用最優解時,通常很直接。假設在原問題中做了貪心選擇而得到了一個子問題,那么需要證明此子問題的最優解與所做的貪心選擇合并后,可以得到原問題的一個最優解,即最終的最優解包含子問題的最優解。通常采用歸納法,證明每個步驟中所做的貪心選擇最終會產生一個最優解。
4. 貪心算法與動態規劃
有兩個經典問題可以舉例表明二者的區別,0/1背包問題和部分背包問題。對于0/1背包問題,由于可能存在背包沒填滿的情況,剩余的空間體積降低了物品的價值。當考慮一件物品是否該加入背包時,必須把該物品加進去的子問題的解與不取該物品的子問題的解進行比較。而這種比較形成了很多子問題重疊,因此可以用動態規劃解決。然而對于部分背包問題,如杭電2111通過單位體積的物品價值排序,每次總是價值最大的裝填,可以保證在裝填任意物品后,背包滿,且價值最大。顯然最優選擇是盡量獲取有剩余的價值最高的物品。很容易看出二者的區別。
轉載于:https://www.cnblogs.com/bombe1013/p/3588682.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的【算法导论】学习笔记——第16章 贪心算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linq to Sql 动态条件另类实现
- 下一篇: 第七课:增量分析