Algorithm Design Methods Greedy Algorithm
by Chin Huang Lin
什麼是「貪心」?
• 常見的貪心:
1. 爸媽買了布丁,偷偷吃掉老哥的 2. 國中生追女生,一個不夠追兩個 3. 期末公佈成績,A 不夠還要 A+
4. 廠商收入縮減,先降低員工薪資 5. 參加朋友喜宴,自備塑膠袋打包 6. ……
• Want more and better!
看不見的樹
• 對於一個問題,我們考慮的每一組方案事實上對應到一組「決策」
• ex. 數獨問題中有 𝑛 格空格,依序為編號為 1~𝑛,那麼我們事實上是在決策 𝑎1, 𝑎2, … , 𝑎𝑛,其中 𝑎𝑖 為第 𝑖 格的值,可以為 1~9 之間的數字。
• 整個決策的過程可以畫成一棵樹,每個葉節點對應到一個可能的方案,其 中有些滿足所有條件形成解,其他則否
• ex.
𝑎
1= 1 𝑎
1= 2
𝑎
1= ⋯ 𝑎
1= 9
𝑎
2= 1 𝑎
2= 2 𝑎
2= ⋯ 𝑎
2= 9
𝑎
𝑖= 1 𝑎
𝑖= ⋯
𝑎
𝑖= 9
𝑎
(𝑛-1)= 1 𝑎
(𝑛-1)= ⋯ 𝑎
(𝑛-1)= 9
𝑎
𝑛= 1
𝑎
𝑛= ⋯
枚舉在幹麼?
• 枚舉事實上就是試圖拜訪整棵決策樹,找出樹裡的解節點
• 剪枝事實上就是根據一些推理排除絕對不可能的分支
• 有時候,我們可以根據一些問題的特性,確定解節點所在的分支!
• 總是選擇當前看起來最有利的分支,然後義無反顧
𝑎
1= 1
𝑎
1= 2 𝑎
1= ⋯ 𝑎
1= 9
𝑎
2= 1 𝑎
2= 2
𝑎
2= ⋯ 𝑎
2= 9
𝑎
𝑖= 1 𝑎
𝑖= ⋯
𝑎
𝑖= 9
𝑎
(𝑛-1)= 1 𝑎
(𝑛-1)= ⋯ 𝑎
(𝑛-1)= 9
𝑎
𝑛= 1 𝑎
𝑛= ⋯
5 8 𝒂
𝟏2 𝒂
𝟐7
3 𝒂
𝟑1
生活中的貪心 (一)
• 黑猩國是一個由大量的黑腥猩建立的國度,裡面共有 𝑛 種面額的貨幣。其 中必定有一種面額是 1 元,剩餘的面額不一定,但對於任意兩種面額 𝑎, 𝑏 (𝑎 ≦ 𝑏),必定有 𝑎 | 𝑏。那麼當黑腥猩要付 𝑥 元購物的時候,最少需要用 到幾個貨幣呢?
• 𝑛 ≦ 30,𝑥 ≦ 2147483647
這麼簡單,我幼稚園就會了!
• 現行的貨幣在不考慮 20 元的情況下事實上就滿足條件
• 生活中你都怎麼付款?
• 當然都盡量以大面額的付阿!
• 為什麼呢?
♪ 想一想:如果沒有「任意兩面額必定有一者是另一者的因數」這個條件,
這樣做還會正確嘛?為什麼?
生活中的貪心 (二)
• Zerojudge b105 誰先晚餐 (2005 NPSC 國中組決賽)
•
http://zerojudge.tw/ShowProblem?problemid=b105
• 生活中,你會怎麼做?
• 當然是先讓吃最慢的人吃阿!
• 為什麼呢?
貪心法的簡單證明
老師,我這題這樣做有什麼問題?
嗯……你怎麼知道你這作法是對的?
可是
可是我範測和自己產的測資都對阿
可是
而且我也想不到更好的方法了
貪心法的簡單證明
• 一時找不到反例,不代表這個作法是對的
• 輸入有這麼多種可能,有測到的佔不到 1%,這樣就說正確的話……
• 不就跟只訪問 4 個人他們總統選舉會投誰,就斷定誰會當選一樣?
• 想不到更好的方法,不構成這個作法的證明
• 怎麼知道不是運氣不好或者資質駑鈍,恰好沒有想到更好的方案?
• 貪心法需要更積極的證明方式!
貪心法的簡單證明
• 對於一個問題 P,提出一個作法 A
• 目標:證明 A 給出的解 S 總是最優的
• 先假設 A 給出的解 S 在某種情況下不是最優的
• 假設此時 P 的真正最優解應為 S’,那麼證明 S’ 不存在 (利用矛盾)
• 通常有兩個方法:
1. 對於任意的 𝑆’,都構造出一組相異於 𝑆’ 的解 𝑆’’,並且滿足 𝑆’’ 比 𝑆’ 還好 2. 設法證明 𝑆 不比 𝑆’ 還糟
• 於是 A 給出的解 S 總是最優的
貪心法的簡單證明
• Zerojudge b105 誰先晚餐 (2005 NPSC 國中組決賽)
• 符號定義:對於一組方案 𝑆,用 |𝑆| 表示 𝑆 方案下全部的人都吃完飯的時間
• 證明架構:
1. 為了方便表示與比較,先用代數表達出問題與解答的數學模型
2. 假設我們的算法給出的解 𝑆 是錯的,那麼存在真正的最優解 𝑆’,且 |𝑆’| < |𝑆|
3. 如果有兩個人編號分別為 𝑖, 𝑗 (編號就代表吃飯的順序) 滿足「𝑖 < 𝑗 且 𝑖 吃得比 𝑗 快」,我們就說這兩人形成一組「逆序對」。既然最優解 𝑆’ ≠ 𝑆,那麼 𝑆’ 裡面 一定存在相鄰的兩元素形成逆序對 (想想看,為什麼)
4. 透過把這兩個人的順序交換,獲得方案 𝑆1′,並證明 |𝑆1′| ≦ |𝑆’|
5. 如果 𝑆1′ 中還存在相鄰逆序,則再把該對逆序元素交換形成 𝑆2′,類似 4 的證明 可知 |𝑆2′| ≦ |𝑆1′|
6. 不斷重複類似 5 的步驟,直到當前的解 𝑆𝑥′ 中不存在相鄰逆序。此時 𝑆𝑥′ 必定不 存在任何逆序對 (想想看,為什麼),從而有 𝑆𝑥′ = 𝑆
7. 於是有 𝑆 ≦ |𝑆𝑥′| ≦ |𝑆𝑥−1′ | ≦ ⋯ ≦ |𝑆1′| ≦ |𝑆′|,即 𝑆 ≦ 𝑆′ ,與 𝑆′ < |𝑆| 的假 設矛盾,從而證明 𝑆 是最佳解
貪心法的簡單證明
1. 為了方便表示與比較,先用代數表達出問題與解答的數學模型
• 一組方案中,設吃飯順序依序為 {1,2, … , 𝑛},則
• 吃飯所需時間依序以 {𝑒1, 𝑒2, … , 𝑒𝑛} 來代表
• 料理所需時間依序以 {𝑐1, 𝑐2, … , 𝑐𝑛} 來代表
• 由於廚師一定不會停手,第 𝑥 個人吃完飯的時間為 𝑓(𝑥) = σ𝑗=1𝑥 𝑐𝑗 + 𝑒𝑥
• 題目要求 max{𝑓(𝑥)|1 ≦ 𝑥 ≦ 𝑛} 盡量小
貪心法的簡單證明
2. 假設存在真正的最優解 𝑆’,且 |𝑆’| < |𝑆|
3. 既然最優解 𝑆’ ≠ 𝑆,那麼 𝑆’ 裡面一定存在相鄰的兩元素形成逆序對
• 不妨假設就是第 𝑖 個人和第 𝑖 + 1 個人形成相鄰逆序對
貪心法的簡單證明
4. 透過把這兩個人的順序交換,獲得方案 𝑆 1 ′ ,並證明 |𝑆 1 ′ | ≦ |𝑆’|
5. 如果 𝑆 1 ′ 中還存在相鄰逆序,則再把該對逆序元素交換形成 𝑆 2 ′ ,類似 4 的證明可知 |𝑆 2 ′ | ≦ |𝑆 1 ′ |
6. 不斷重複類似 5 的步驟,直到當前的解 𝑆 𝑥 ′ 中不存在相鄰逆序。此時 𝑆 𝑥 ′ 必定不存在任何逆序對,從而有 𝑆 𝑥 ′ = 𝑆
7. 於是有 𝑆 ≦ |𝑆 𝑥 ′ | ≦ |𝑆 𝑥−1 ′ | ≦ ⋯ ≦ |𝑆 1 ′ | ≦ |𝑆 ′ |,即 𝑆 ≦ 𝑆 ′ ,與 𝑆 ′ <
|𝑆| 的假設矛盾,從而證明 𝑆 是最佳解
• 事實上要證明的只有兩件事情:
1) 對於一個存在相鄰逆序對的方案 𝑆𝑗′,可以透過交換該組逆序對獲得 𝑆𝑗+1′ ,且 |𝑆𝑗+1′ | ≦ |𝑆𝑗′| 2) 不斷重複地把相鄰逆序對交換,總有一天會變成一組不存在相鄰逆序的方案
貪心法的簡單證明
1) 對於一個存在相鄰逆序對的方案 𝑆 𝑗 ′ ,可以透過交換該組逆序對獲得 𝑆 𝑗+1 ′ ,且 |𝑆 𝑗+1 ′ | ≦ |𝑆 𝑗 ′ |
• 𝑆𝑗′ 的情形:
• 吃飯順序依序為 {1,2, … ,
𝑖, 𝑖 + 1, … ,
𝑛}• 吃飯所需時間依序為 {𝑒1, 𝑒2, … ,
𝑒
𝑖,𝑒
𝑖+1, … , 𝑒𝑛}• 料理所需時間依序為 {𝑐1, 𝑐2, … ,
𝑐
𝑖,𝑐
𝑖+1, … , 𝑐𝑛}• 第 𝑥 個人吃完飯的時間為 𝑓(𝑥) = σ𝑗=1𝑥 𝑐𝑗 + 𝑒𝑥
• 第 𝑖 個人和第 𝑖 + 1 個人形成相鄰逆序對
• 𝑆𝑗′ =
max 𝑓 𝑥 𝑥 ≠ 𝑖 && 𝑥 ≠ 𝑖 + 1 , 𝑓 𝑖 , 𝑓 𝑖 + 1 )
• 𝑆𝑗+1′ 的情形:
• 吃飯順序依序為 {1,2, … ,
𝑖 + 1, 𝑖, … , 𝑛}
• 吃飯所需時間依序為 {𝑒1, 𝑒2, … ,
𝑒
𝑖+1,𝑒
𝑖, … , 𝑒𝑛}• 料理所需時間依序為 {𝑐1, 𝑐2, … ,
𝑐
𝑖+1,𝑐
𝑖, … , 𝑐𝑛}• 第 𝑥 個人吃完飯的時間為 𝑓′(𝑥),等下討論
• 第 𝑖 個人和第 𝑖 + 1 個人
不再是相鄰逆序對
• 𝑆𝑗+1′ =
max 𝑓′ 𝑥 𝑥 ≠ 𝑖 && 𝑥 ≠ 𝑖 + 1 , 𝑓′ 𝑖 , 𝑓′ 𝑖 + 1 )
貪心法的簡單證明
1) 對於一個存在相鄰逆序對的方案 𝑆 𝑗 ′ ,可以透過交換該組逆序對獲得 𝑆 𝑗+1 ′ ,且 |𝑆 𝑗+1 ′ | ≦ |𝑆 𝑗 ′ |
• 𝑓’(𝑥):
• 對於 𝑥 < 𝑖,𝑓’(𝑥) = σ𝑗=1𝑥 𝑐𝑗 + 𝑒𝑥 = 𝑓(𝑥)
• 對於 𝑥 > 𝑖 + 1,𝑓’ 𝑥 = σ𝑗=1𝑖−1 𝑐𝑗 + 𝑐𝑖+1 + 𝑐𝑖 + σ𝑗=𝑖+1𝑥 𝑐𝑗 + 𝑒𝑥 = σ𝑗=1𝑥 𝑐𝑗 + 𝑒𝑥 = 𝑓(𝑥)
• 𝑓’(𝑖) = σ𝑗=1𝑖−1 𝑐𝑗 + 𝑐𝑖+1 + 𝑒𝑖+1
• 𝑓’(𝑖 + 1) = σ𝑗=1𝑖−1 𝑐𝑗 + 𝑐𝑖+1 + 𝑐𝑖 + 𝑒𝑖
• 發現
max(
𝑓
′𝑥 │𝑥 ≠ 𝑖 && 𝑥 ≠ 𝑖 + 1
, 𝑓′ 𝑖 , 𝑓′ 𝑖 + 1 )= max(
𝑓 𝑥 │, 𝑥 ≠ 𝑖 && 𝑥 ≠ 𝑖 + 1
, 𝑓′ 𝑖 , 𝑓′ 𝑖 + 1 )• 𝑆𝑗+1′ 的情形:
• 吃飯順序依序為 {1,2, … ,
𝑖 + 1, 𝑖, … , 𝑛}
• 吃飯所需時間依序為 {𝑒1, 𝑒2, … ,
𝑒
𝑖+1,𝑒
𝑖, … , 𝑒𝑛}• 料理所需時間依序為 {𝑐1, 𝑐2, … ,
𝑐
𝑖+1,𝑐
𝑖, … , 𝑐𝑛}• 第 𝑥 個人吃完飯的時間為 𝑓′(𝑥),等下討論
• 第 𝑖 個人和第 𝑖 + 1 個人
不再是相鄰逆序對
• 𝑆𝑗+1′ =
max 𝑓′ 𝑥 𝑥 ≠ 𝑖 && 𝑥 ≠ 𝑖 + 1 , 𝑓′ 𝑖 , 𝑓′ 𝑖 + 1 )
貪心法的簡單證明
1) 對於一個存在相鄰逆序對的方案 𝑆 𝑗 ′ ,可以透過交換該組逆序對獲得 𝑆 𝑗+1 ′ ,且 |𝑆 𝑗+1 ′ | ≦ |𝑆 𝑗 ′ |
• 𝑓’(𝑥):
• 對於 𝑥 < 𝑖,𝑓’(𝑥) = σ𝑗=1𝑥 𝑐𝑗 + 𝑒𝑥 = 𝑓(𝑥)
• 對於 𝑥 > 𝑖 + 1,𝑓’ 𝑥 = σ𝑗=1𝑖−1 𝑐𝑗 + 𝑐𝑖+1 + 𝑐𝑖 + σ𝑗=𝑖+1𝑥 𝑐𝑗 + 𝑒𝑥 = σ𝑗=1𝑥 𝑐𝑗+ 𝑒𝑥 = 𝑓(𝑥)
• 𝑓’(𝑖) = σ𝑗=1𝑖−1 𝑐𝑗 + 𝑐𝑖+1 + 𝑒𝑖+1
• 𝑓’(𝑖 + 1) = σ𝑗=1𝑖−1 𝑐𝑗 + 𝑐𝑖+1 + 𝑐𝑖 + 𝑒𝑖
• 發現
max(
𝑓
′𝑥 │𝑥 ≠ 𝑖 && 𝑥 ≠ 𝑖 + 1
, 𝑓′ 𝑖 , 𝑓′ 𝑖 + 1 )= max(
𝑓 𝑥 │, 𝑥 ≠ 𝑖 && 𝑥 ≠ 𝑖 + 1
, 𝑓′ 𝑖 , 𝑓′ 𝑖 + 1 )• 比較 |𝑆𝑗′| 與 |𝑆𝑗+1′ | :
• 為了簡潔,用 𝛼 代表
𝑓
′𝑥 │𝑥 ≠ 𝑖 && 𝑥 ≠ 𝑖 + 1
• 𝑆𝑗′ = max 𝛼, 𝑓 𝑖 , 𝑓 𝑖 + 1
• 𝑆𝑗+1′ = max 𝛼, 𝑓′ 𝑖 , 𝑓′ 𝑖 + 1
• 問題:max(𝑓(𝑖), 𝑓(𝑖 + 1)), max(𝑓’(𝑖), 𝑓’(𝑖 + 1)),誰大?
貪心法的簡單證明
1) 對於一個存在相鄰逆序對的方案 𝑆 𝑗 ′ ,可以透過交換該組逆序對獲得 𝑆 𝑗+1 ′ ,且 |𝑆 𝑗+1 ′ | ≦ |𝑆 𝑗 ′ |
• 𝑓 𝑖 , 𝑓 𝑖 + 1 , 𝑓′ 𝑖 , 𝑓′(𝑖 + 1):
• 已知條件:𝑒𝑖 < 𝑒𝑖+1 ⇒ 𝑒𝑖+1 − 𝑒𝑖 > 0
• 為了簡潔,用 𝑘 代表 σ𝑗=1𝑖−1 𝑐𝑗
• 𝑓 𝑖 = 𝑘 + 𝑐𝑖 + 𝑒𝑖
• 𝑓 𝑖 + 1 = 𝑘 + 𝑐𝑖 + 𝑐𝑖+1 + 𝑒𝑖+1
• 𝑓’ 𝑖 = 𝑘 + 𝑐𝑖+1 + 𝑒𝑖+1
• 𝑓’ 𝑖 + 1 = 𝑘 + 𝑐𝑖+1 + 𝑐𝑖 + 𝑒𝑖
• 𝑓 𝑖 + 1 − 𝑓 𝑖 = 𝑐𝑖+1 + 𝑒𝑖+1 − 𝑒𝑖 > 0
• 𝑓 𝑖 + 1 − 𝑓′ 𝑖 = 𝑐𝑖 > 0
• 𝑓 𝑖 + 1 − 𝑓′ 𝑖 + 1 = 𝑒𝑖+1 − 𝑒𝑖 > 0
♪ 𝑓(𝑖 + 1) 比其他三者都還大,從而有
max 𝑓 𝑖 , 𝑓 𝑖 + 1 > max(𝑓’(𝑖), 𝑓’(𝑖 + 1))
• 比較 |𝑆𝑗′| 與 |𝑆𝑗+1′ | :
• 為了簡潔,用 𝛼 代表
𝑓
′𝑥 │𝑥 ≠ 𝑖 && 𝑥 ≠ 𝑖 + 1
• 𝑆𝑗′ = max 𝛼, 𝑓 𝑖 , 𝑓 𝑖 + 1
• 𝑆𝑗+1′ = max 𝛼, 𝑓′ 𝑖 , 𝑓′ 𝑖 + 1
• 問題:max(𝑓(𝑖), 𝑓(𝑖 + 1)), max(𝑓’(𝑖), 𝑓’(𝑖 + 1)),誰大?
貪心法的簡單證明
2) 不斷重複地把相鄰逆序對交換,總有一天會變成一組不存在相鄰逆 序的方案
• 根據逆序對的定義可知,每次交換後,逆序對總數會 -1
• 由「逆序對數不為 0 則存在相鄰逆序對」可知,永遠找得到相鄰逆序 對交換
• 逆序對數為 0 時,顯然相鄰逆序對數也為 0,得証
不直接的貪心
• UVa 714 Copying Books
•
http://uva.onlinejudge.org/external/7/714.html
• 為了懲罰你和你的朋友們 (共 𝑚 個人) 一起把垃圾偷偷丟到隔壁班的花盆裡,老師精選 了 𝑛 篇的文章給你們在午休時站著罰抄。
• 這 𝑛 篇文章在排成一列的 𝑚 個人面前排成一列,為了作業方便你們決定每個人都只能 負責抄寫其中連續排列的若干篇文章 (例如某個人可以負責抄寫第 2~5 篇文章,卻不能 夠負責抄寫第 2,3,5,8 篇文章);而且為了工整性,老師要求一篇文章一定只能由一個人 抄寫,否則會有不同的字跡。
• 由於你們的感情很好,所以就算每個人負責的份量不同也不會吵架。但是為了早點抄完回 去打鬧,你們希望負責份量最多的人負責的份量盡量少。
• 在你們已經知道這 𝑛 篇文章的頁數依序為 {𝑝1, 𝑝2, … , 𝑝𝑛},請問負責份量最多的那位同學 最少要負責幾頁的抄寫量呢?
一點瓶頸
• 如果後面人還很多,就應該抄少一點;如果後面人少,就應該抄多一點
• 但是怎麼拿捏呢?
• 如果自己不是第一名,那應該盡量抄多一點;如果自己是第一名,那應該盡量抄少一點;
但是第一名又必須要是第一名(?)
• 如果我們知道到底第一名最後抄多少書就好了……
• 最優化決策很難 (要把決策樹上所有葉節點拿出來比較),但是判定問題簡單很多──怎麼 把最優化決策問題轉為判定問題呢?
• 當然就是枚舉啦!
• 直接枚舉第一名要抄多少頁 (其實就是枚舉每個人最多不能夠超過多少頁),然後貪心地 盡量抄到不能再抄
• 如果抄不完,代表當前枚舉得太理想
• 複雜度 𝑂(𝑚 σ𝑖=1𝑛 𝑝𝑖),好慢!
有點單調
• 我們要求的是「抄得完書的情況下,負擔最重的人要抄的最少頁數 𝑝」
• 如果我們枚舉負擔最重的人要抄 𝑥 頁,那麼對於所有 𝑥 < 𝑝,一定都抄 不完;對於所有 𝑥 ≧ 𝑝,一定都抄得完
• 不就是摔蛋問題嘛?
• 馬上把枚舉的部份改成二分枚舉,複雜度降為 𝑂(𝑚log σ𝑖=1𝑛 𝑝𝑖)
霍夫曼編碼
• 一般而言,電腦中的每個字元都以相同的位元數來儲存,舉例而言只要是 char 都用 8 bits 來儲存,因此有 𝑛 個字元,就會佔用 8𝑛 bits
• 如果已經知道哪些字元各會出現幾次,事實上我們有更好的辦法!舉例來 說:
• 基因序列裡只會有四種字元:ATCG
• 已知 A 出現 185 次,T 出現 47 次,C 出現 59 次,G 出現 308 次
• 兩種不同的表達法:
• 左邊的表達法總共需要 1198 bits,右邊的表達法只需要 996 bits
A T C G
00 01 10 11
A T C G
10 101 100 0
非固定長度編碼
• 問:為什麼不要用更短的編碼?
• ex.
• 答:這樣子在解釋 000 時會有歧異,可解釋為 CG 或 GC
• 所以任意字元的編碼不能是另一字元編碼的前綴 (prefix)
• 這代表所有字元的編碼 (即一個編碼方案) 可以形成一棵 tree!
• 其中最優 (最省空間) 的編碼方案對應到的 tree,稱為最優編碼樹
A T C G
1 01 00 0
最優編碼樹
• 右邊是一棵當文本是「THIS IS THE TEST TEXT XDDD」時的最優編碼樹
• 最優編碼樹的一些性質
1. 一定不會有只有一個兒子的節點
2. 頻率越高的字元對應的葉節點深度越淺
3. 必定存在一棵最優編碼樹,使得頻率最低的兩個字 元對應的葉節點形成兄弟
4. 定義 𝑓𝑠(𝑥) 為節點 𝑥 形成的子樹中,所有葉節點 的頻率和。則某編碼樹為 𝑇0,把 𝑇0 中某節點 𝑥 形成的子樹整棵替換為一個頻率為 𝑓𝑠(𝑥) 的字元形 成新樹 𝑇,那麼 𝑇 為新字元集的最優編碼樹當起 僅當 𝑇0 為最優編碼樹。
圖片來源: http://huffman.ooz.ie/
最優編碼樹
1. 一定不會有只有一個兒子的節點
• 否則我們直接用這個節點的子節點取代它自己,依舊是合法的編碼樹但空間消耗更小
最優編碼樹
2. 頻率越高的字元對應的葉節點深度越淺
• 否則我們交換兩者的位置,空間消耗更小
最優編碼樹
3. 必定存在一棵最優編碼樹,使得頻率最低的兩個字元對應的葉節點形 成兄弟
• 由性質 1 可知深度最大的一層至少有兩個葉節點
• 再配合性質 2 可確定頻率最低的兩個字元皆位於深度最大的一層
• 如果兩者並非兄弟,則把他們位置換成兄弟,解的優劣不變
最優編碼樹
4. 某編碼樹為 𝑇 0 ,把 𝑇 0 中某節點 𝑥 形成的子樹整棵替換為一個頻 率為 𝑓𝑠(𝑥) 的字元形成新樹 𝑇,那麼 𝑇 為新字元集的最優編碼樹 當起僅當 𝑇 0 為最優編碼樹
圖片來源: http://huffman.ooz.ie/
最優編碼樹
4. 某編碼樹為 𝑇 0 ,把 𝑇 0 中某節點 𝑥 形成的子樹整棵替換為一個頻 率為 𝑓𝑠(𝑥) 的字元形成新樹 𝑇,那麼 𝑇 為新字元集的最優編碼樹 當起僅當 𝑇 0 為最優編碼樹
• 每個葉節點貢獻的空間消耗量為「字元頻率×節點深度」
• 設節點 𝑥 形成的子樹中有 𝑛 個葉節點,頻率分別為 {𝑓1, 𝑓2, … , 𝑓𝑛},與節點 𝑥 的深度差分別為 {𝑙1, 𝑙2, … , 𝑙𝑛}
• 當節點 𝑥 的深度為 𝑑 時,整棵子樹的空間消耗量為
𝑖=1 𝑛
𝑓𝑖 𝑙𝑖 + 𝑑 =
𝑖=1 𝑛
𝑓𝑖𝑙𝑖 + 𝑑
𝑖=1 𝑛
𝑓𝑖 =
𝑖=1 𝑛
𝑓𝑖𝑙𝑖 + 𝑑 𝑓𝑠(𝑥)
• 假如把 𝑥 形成的子樹整棵替換為一個頻率為 𝑓𝑠(𝑥) 的字元形成的葉節點,新得 到的樹卻不是最優編碼樹的話……
最優編碼樹
𝑥
原先的最優編碼樹 𝑇0 總空間消耗= 𝑥 子樹消耗
+其他部份消耗 1
𝑇0 變換節點後的編碼樹 𝑇 總空間消耗= 𝑥 子樹消耗
+其他部份消耗 1 -σ𝑖=1𝑛 𝑓𝑖𝑙𝑖
頻率= 𝑓𝑠(𝑥) 頻率= 𝑓𝑠(𝑥)
假設中比 𝑇 更好的最優編碼樹 𝑇′
總空間消耗= 𝑥 子樹消耗
+其他部份消耗 2 -σ𝑖=1𝑛 𝑓𝑖𝑙𝑖
把 𝑇′ 中的紅點再次換回 𝑥 子樹的 𝑇0′ 總空間消耗= 𝑥 子樹消耗
+其他部份消耗 2
𝑥
• 根據假設,必須有 其他部份消耗1 > 其他部份消耗2
• 從而 𝑇0′ 優於 𝑇0,與假設矛盾!
證明時間
4. 某編碼樹為 𝑇 0 ,把 𝑇 0 中某節點 𝑥 形成的子樹整棵替換為一個頻 率為 𝑓𝑠(𝑥) 的字元形成新樹 𝑇,那麼 𝑇 為新字元集的最優編碼樹 當起僅當 𝑇 0 為最優編碼樹
• 每個葉節點貢獻的空間消耗量為「字元頻率×節點深度」
• 設節點 𝑥 形成的子樹中有 𝑛 個葉節點,頻率分別為 {𝑓1, 𝑓2, … , 𝑓𝑛},與節點 𝑖 的深度差分別為 {𝑙1, 𝑙2, … , 𝑙𝑛}
• 當節點 𝑥 的深度為 𝑑 時,整棵子樹的空間消耗量為
𝑖=1 𝑛
𝑓𝑖 𝑙𝑖 + 𝑑 =
𝑖=1 𝑛
𝑓𝑖𝑙𝑖 + 𝑑
𝑖=1 𝑛
𝑓𝑖 =
𝑖=1 𝑛
𝑓𝑖𝑙𝑖 + 𝑑 𝑓𝑠(𝑥)
• 假如把 𝑥 形成的子樹整棵替換為一個頻率為 𝑓𝑠(𝑥) 的字元形成的葉節點,新得 到的樹卻不是最優編碼樹的話……
• 類似地如果 𝑇 是最優編碼樹,但 𝑇0 不是最優編碼樹的話……
最優編碼樹
𝑥
原先的編碼樹 𝑇0
總空間消耗= 𝑥 子樹消耗
+其他部份消耗 1 𝑇0 變換節點後的最優編碼樹 𝑇
總空間消耗= 𝑥 子樹消耗
+其他部份消耗 1 -σ𝑖=1𝑛 𝑓𝑖𝑙𝑖
頻率= 𝑓𝑠(𝑥)
假設中比 𝑇0更好的最優編碼樹 𝑇0′ 總空間消耗= 𝑥 子樹消耗
+其他部份消耗 2
• 根據假設,必須有 其他部份消耗1 > 其他部份消耗2
• 從而 𝑇′ 優於 𝑇,與假設矛盾!
𝑥
頻率= 𝑓𝑠(𝑥)
把 𝑇0′ 中紅點換回 𝑥 子樹的 𝑇′
總空間消耗= 𝑥 子樹消耗
+其他部份消耗 2 -σ𝑖=1𝑛 𝑓𝑖𝑙𝑖
霍夫曼編碼
1. 把所有字元都視為一棵單節點樹,初始權重為字元頻率,全部的字元形成 一個森林
2. 每次從森林裡面取出權重最小的兩棵樹,並把它們合併成一棵樹,權重為 兩棵樹的權重和
3. 把合併後獲得的樹再加回去森林中,重複 2 直到森林中剩下一棵樹
4. 此時該樹即為最優編碼樹
霍夫曼編碼
F: 2 O: 3 E: 5 R: 4 G: 4 T: 7
圖片來源: http://zh.wikipedia.org/wiki/File:Huffman_algorithm.gif
野生的新證明手法
• 我們目前已經學過:
• 數學歸納法
• 直接反證法
• 遞迴證明法!
1) 定義 𝑃 𝑛 為輸入規模為 𝑛 時的子問題 2) 證明當 𝑛 = 1 時,命題成立
3) 證明已知包含 𝑃 𝑛−1 的解的情況下,貪心策略正確 4) 證明存在 𝑃 𝑛 的解包含 𝑃 𝑛−1 的解
5) 命題得證
野生的新證明手法
1) 定義 𝑃 𝑛 為輸入規模為 𝑛 時的子問題
• 定義 𝑃𝑛 為共有 𝑛 種字元時的最佳解
2) 證明當 𝑛 = 1 時,命題成立
• 不能更明顯了 XD
3) 證明已知包含 𝑃 𝑛−1 的解的情況下,貪心策略正確
• 由性質 3,至少存在一組解包含此貪心策略
4) 證明存在 𝑃 𝑛 的解包含 𝑃 𝑛−1 的解
• 根據性質 4,找一個恰包含兩葉節點的子樹 (根據性質 1,只要 𝑛 ≧ 2 這樣的子樹 必定存在) 進行縮點,此時 𝑃𝑛 的解必定包含 𝑃𝑛−1 的解