第四章 貪心算法
這里需要注意的便是如何證明貪心算法得到的是最優解。
下面來一些例子:
1. 活動選擇問題
現在感覺貪心算法真的是目前遇到過實現起來最簡單的一個,但是問題在於用貪心算法得到的解是不是最優解呢?下面來證明:
第一步要證明問題具有最優子結構性質:
還是利用了這種先假設,再反證這種策略。對於最優解,如果這個解中所對應於子問題的子解不是子問題的最優解的話,那么對於在這個子問題的最優解,它和我們除掉的其余子問題的子解合並回到整個問題的解時一定會優於我們一開始假設的最優解,矛盾。故的出最優解的子解一定是子問題的最優解,即最優子結構性質。
第二步證明貪心選擇性:
(1) 假定首選元素不是貪心選擇所要的元素,證明將首元素替換成貪心選擇所需元素,依然得到最優解;
(2) 數學歸納法證明每一步均可通過貪心選擇得到最優解
這個思路很簡單,如果最優解第一步不選f1,因為這個活動結束時間最早,所以它一定可以替換最優解中的第一個活動,並且S的最大相容集合並未減少,即將首元素替換成貪心選擇所需元素,依然得到了最優解,故得證貪心選擇性。
2. 哈弗曼編碼
哈哈,考研數據結構有提到這個,就是要構造一棵帶權路徑長度最小的二叉樹,這個很簡單,就是每一步從所有節點中選擇權值最小的兩個節點合並成新的節點放入到原來的節點集合中,這個新的節點的權值等於原來兩個節點的權值之和。之所以說是貪心算法是因為每一步都在當前節點集合中選當前權值最小的兩個。
這里要注意的還是證明:
“因為z是C‘中的字符,所以它必為T” 中的葉子節點”,這句話該怎么理解呢?z是C’中的字符,按照哈夫曼樹的構造規則,原先所有的節點構造后都在葉節點的位置上,所以z無論是在T’中還是T"中都作為葉節點存在(當然在T中不是,因為在T中z是一個中間節點的存在,連接x和y)。。。。。不過說實在的,關於這塊最優子結構的證明我還是有些疑惑,也說不上來問題在哪。。。。 日后分析分析,現在考試為重。
3. 並查集
4. 最小生成樹
考研數據結構里,這部分內容算是重點章節了吧。主要就是兩個算法:克魯斯卡爾(Kruskal)算法和普里姆(Prim)算法。克魯斯卡爾(Kruskal)算法在圖中每次選擇權值最小的邊,判斷兩端點是否屬於不同集合,若是的話加入這條邊將這兩個端點連接成同一個集合。重復如此過程直至所有頂點在同一集合中。克魯斯卡爾(Kruskal)算法經常需要判斷權值最小的邊的兩端是否屬於不同連通分量,所以可使用並查集技術加快判斷速度。
剩下的就是證明這塊了:
這里的貪心選擇性證明和前幾題思路貌似有點不同,利用的是"假設--反證--矛盾"的策略。
5. 最短路徑
又是考研數據結構中的知識,記得主要有兩個算法:Dijkstra算法和Floyd算法,當初為了理解這兩個算法死了多少腦細胞。。。。。 淚。。。。。
獲取最短路徑的方法:按照p和d數組反向讀即可。比如到節點4的最短距離,看數組元素d[4]和p[4], d[4]=60, 那么得源點0到節點4的最短距離是60,p[4]=2, p[2]=3, p[3]=0, 得最短路徑是0-3-2-4
國際慣例,最后的證明:
6. 個人總結
關於貪心算法,在問題的分析以及算法的實現上,個人覺得比動態和分治要簡單。重要的是確定問題能用貪心算法得到最優解,即本章節中反復證明的最優子結構和貪心選擇性。只有滿足了這兩個要素才能用貪心算法去解決問題。