• 沒有找到結果。

分治 Divide and Conquer Lecture & modified by baluteshih Credit by yp155136 Credit by TreapKing

N/A
N/A
Protected

Academic year: 2022

Share "分治 Divide and Conquer Lecture & modified by baluteshih Credit by yp155136 Credit by TreapKing"

Copied!
105
0
0

加載中.... (立即查看全文)

全文

(1)

分治 Divide and Conquer

Lecture & modified by baluteshih Credit by yp155136

Credit by TreapKing

(2)

Q & A

• 影片有什麼問題嗎?

(3)

何時使用分治

• 經驗!

刷題!

(4)

何時使用分治

• 經驗!

刷題!

• 面對一個問題時,怎麼枚舉都找不到優化的切入點

• 突發奇想從中間切一半,就可能找到很棒的 conquer 性質

• 當這個性質足夠讓我們在良好的複雜度解決 conquer 時,就 可能可以在犧牲頂多一個 log 的情況下完成整個問題

• 「在 conquer 時能夠省去維護儲存所有資訊的力氣,只需要專 心處理跨分隔線的資訊」,就是分治的精髓

(5)

分治小技巧

• 養成良好習慣

左閉右閉(我個人常用的方式)

左閉右開

...(?)

• divide 完之後遞迴下去,直接假設遞迴後得到的結果是理想 的,這樣 conquer 的時候會比較好思考

• 當 n 很小的時候,可以暴力做,可能會減少遞迴的 cost

EX: merge sort 到 n 很小時,就隨便用一個 O(n^2) 的 sort

• 多寫題目(?)

(6)

分析遞迴的工具

• 為什麼要學這個

• 可以分析你寫的程式的時間複雜度

• 可以耍帥

• Credit to Algorithm Design and Analysis, 2019 Fall

(7)

先來看看符號的定義

• big-O 定義

• 存在一個常數 c, n_0,使得當 n 比 n_0 大時,f(n) 都會比 c * g(n) 小

• 例如,當 f(n) = x^2 + 10x , g(n) = x^3 時,我們可以 選擇 c = 0.5, n_0 = 10

(8)

分析遞迴的常見手法

• Substitution Method (取代法)

• Recursion-Tree Method (遞迴樹法)

• Master Method (套公式大法/大師法)

(9)

Substitution Method

• 取代法

• 三個大步驟: Guess 、 Verify 、 Solve

• Guess:

猜 f(n) 是屬於哪個複雜度

• Verify:

驗證猜想是否正確

常用 數學歸納法 驗證

• Solve :

解出正確的常數

證明 big-O

(10)

Substitution Method

• 範例:

• 三個大步驟: Guess 、 Verify 、 Solve

(11)

Substitution Method

• 範例:

• 先來做個簡單的化簡,把 big-O 給去掉

• 其中 a, b > 0

(12)

Substitution Method

• 範例:

• 猜測

(13)

Substitution Method

• 猜測

• 使用數學歸納法

n = 1: trivial

(14)

Substitution Method

• 猜測

• 使用數學歸納法

n = 1: trivial

n > 1:

(15)

Substitution Method

• 猜測

• 使用數學歸納法

n = 1: trivial

n > 1:

(16)

Substitution Method

• 猜測

• 使用數學歸納法

n = 1: trivial

n > 1:

• 因此,由數學歸納法,可以得到 T(n) 是 O(N log N) 的

(17)

Substitution Method

• 剛剛的例子似乎沒有用到「解出正確常數」的樣子

• 其實只是運氣特別好(?)

• 讓我們來看更多例子吧

(18)

Substitution Method

• 範例:

• 試證明: T(n) 是 O(n^3)

• Hint:

(19)

Substitution Method

• 來用用數學歸納法吧

• n = 1:trivial

• n > 1:

(20)

Substitution Method

• 來用用數學歸納法吧

• n = 1:trivial

• n > 1:

(21)

Substitution Method

• 來用用數學歸納法吧

• n = 1:trivial

• n > 1:

為了讓不等式成立,

也就是說,cn^3 > 2bn

(22)

Substitution Method

• 來用用數學歸納法吧

• n = 1:trivial

• n > 1:

• 所以,當 時,

T(n) 就是 O(n^3)

為了讓不等式成立,

也就是說,cn^3 > 2bn 我們可以設 c >= 2b, n >= 1

(23)

Substitution Method

• 範例:

• 試證明: T(n) 是 O(n^2)

(24)

Substitution Method

• n = 1 時, trivial

• n > 1 時,

(25)

Substitution Method

• n = 1 時, trivial

• n > 1 時,

• 哇,好像沒辦法繼續推了

• 我們真的猜錯了嗎?

(26)

Substitution Method

• n = 1 時, trivial

• n > 1 時,

• 哇,好像沒辦法繼續推了

• 我們真的猜錯了嗎?

• 其實不全然,但這也是取代法的一個盲點:有的時候猜錯就證不 出來了

(27)

Substitution Method

• n = 1 時,

(28)

Substitution Method

• n = 1 時,

• n > 1 時,

(29)

Substitution Method

• n = 1 時,

• n > 1 時,

為了讓不等式成立,

也就是說,c_2n > bn

(30)

Substitution Method

• n = 1 時,

• n > 1 時,

• 所以,當

時,T(n) 就是 O(n^2) !

為了讓不等式成立,

也就是說,c_2n > bn 我們可以設c_2 >= b, n >= 1

(31)

Substitution Method

• 除了上面那個技巧之外,Substitution 還有一個經典用法:變 數變換

• 例:

(32)

Substitution Method

• 例:

• 變數變換1:

(33)

Substitution Method

• 例:

• 變數變換1:

• 變數變換2:

(34)

Substitution Method

• 例:

• 變數變換1:

• 變數變換2:

• 所以:

(35)

Recursion-Tree Method

• 遞迴樹法

• 顧名思義,就是把遞迴樹畫出來 之後,去把花費的時間總和

算出來

• 算出來之後,在用前面介紹的 substitution method 檢查

• 遞迴樹:遞迴的過程

• 遞迴樹法並不嚴謹,他只能幫你「猜」複雜度

reference:http://kkc47.blogspot .com/2014/08/learning-dynamic- programming-day-1.html

(36)
(37)

Recursion-Tree Method

• 來看個例子

• 例:

• 試試看把遞迴樹畫出來

(38)

Recursion-Tree Method

(39)

Recursion-Tree Method

(40)

Recursion-Tree Method

(41)

Recursion-Tree Method

• 例:

• 可以得到

(42)

Recursion-Tree Method

• 例:

• 可以得到

• 根據等比級數,可得

• 因此,T(n) 是 O(n^2)

• 但這不足以證明 T(n) 是 O(n^2)

• 真的要分析的話,可以試著用數學歸納法

(43)

Master Theorem

• 主定理

• 很好用的工具!

(44)

Master Theorem

• 假設

• Case 1: s.t.

• Case 2: s.t.

• Case 3: s.t.

且 s.t. 在 n 足夠大時

(45)

Master Theorem

• 白話一點 QQ

(46)

Master Theorem

• 白話一點 QQ

• 不嚴謹的說,就是比較 f(n) 跟 的關係

• 如果一樣的話,就加個 log,否則就是比較大的那個

• 以下會分三種情況說明,順便會舉點例子

小於

等於

大於

(47)

Master Theorem

• 比較 f(n) 跟 的關係

• 如果 ,那麼

• 例如,

• 根據主定理,

所以 T(n) 是 O(n^2)

• 可以試著用 Substitution method 寫寫看

• 也可以試著畫畫看 Recursion tree

(48)

Master Theorem

(49)

Master Theorem

• 比較 f(n) 跟 的關係

• 如果 ,那麼

• 例如,

• T(n) = O(n log n) ,前面也有用 substitution 證明過

• 可以想像成原本的複雜度多一個 log

• 在這個 case,f(n) 如果多乘好幾個 log 也沒關係,依然可 以直接多補一個上去

(50)

Master Theorem

• 比較 f(n) 跟 的關係

• 如果 ,那麼

• 例如,

• T(n) = O(n^2) ,前面有用 recursion-tree 證過了

• 這個 case 其實有個額外的條件,但是不常發生(?)

(51)

分析遞迴的工具

• 數學理論的部份就講到這邊啦

• 什麼東西都記不起來,也可以暫時只記得 Master Therorem 就好 XD

• 接下來要講實際上會遇到的題目,前面睡著的可以起床了

(52)

最大連續和

• 給你一個長度為 N 的序列 a_1, a_2, ..., a_N ,請 你找到 (L, R) ,滿足 a_L + ... + a_R 最大

• N <= 10^5

• 先來想想看要怎麼做

• 練習題

https://zerojudge.tw/ShowProblem?problemid=d784

(53)

最大連續和

• O(N^3)

• O(N^2)

• O(N log N)

• O(N) (?)

• 那換一個限制,只能用「分治法」來做

因為我們現在在教分治嘛

(54)

最大連續和

• 答案有 O(N^2) 種

• 我們有沒有辦法好好的 divide 成一半,然後想盡辦法 conquer 起來呢?

(55)

最大連續和

• 是可以的!

• 我們先把序列切成兩半,左右遞迴求出各自半部的最佳解

Solve(L, R) 會回傳 a_L, ..., a_R 的最佳解

(56)

最大連續和 --- conquer

• 跨過兩側,一定會拿 a[mid] 跟 a[mid + 1]

• 所以我們要求的東西 a[L] + ... + a[R],可以換成找 (a[L] + ... + a[mid]) + (a[mid + 1] + ... + a[R])

• 有沒有發現,上面的式子就是從中間點開始,往左 & 往右的走 一段路後,得到的總和

• 於是乎,取「從中間往左加的最大值」加上「從中間往右加的最大 值」,最後加起來就完成 conquer 的部份了

(57)

最大連續和

(58)

最大連續和

• 複雜度分析

(59)

最大連續和

• 複雜度分析

• 假設 T(n) 是 solve() 的長度為 n 的複雜度

• 那麼,T(n) = 2T(n / 2) + O(n)

(60)

最大連續和

• 複雜度分析

• 假設 T(n) 是 solve() 的長度為 n 的複雜度

• 那麼,T(n) = 2T(n / 2) + O(n)

• 所以,最後的複雜度是 T(n) = O(n log n)

(61)

最大連續和

• 複雜度分析

• 假設 T(n) 是 solve() 的長度為 n 的複雜度

• 那麼,T(n) = 2T(n / 2) + O(n)

• 所以,最後的複雜度是 T(n) = O(n log n)

• Challenge:用分治法可以做到 O(n) 嗎?

(62)

多項式乘法

• 給你兩個 n 次多項式,請你求出兩個多項式的乘積。

• Ex:

• 練習題:https://tioj.ck.tp.edu.tw/problems/1064

拿部份分數就好了(?)

把 x 當成 10 這樣

(63)

多項式乘法

• 給你兩個 n 次多項式,請你求出兩個多項式的乘積。

• Ex:

• 來想想看要怎麼做吧

(64)

多項式乘法

• Naïve作法

• 用個雙重迴圈跑一跑乘一乘加一加

• 時間複雜度是 O(n^2)

(65)

多項式乘法

• Naïve作法

• 用個雙重迴圈跑一跑乘一乘加一加

• 時間複雜度是 O(n^2)

• 好慢(?)

• 有沒有更快的方式?

(66)

多項式乘法

• Naïve作法

• 用個雙重迴圈跑一跑乘一乘加一加

• 時間複雜度是 O(n^2)

• 據說在古早的時代,從來沒有人質疑過乘法可以做得更快

• 可能會有人想到 FFT(Fast Fourier Transform,快速傅立 葉轉換),但我現在沒有要講這個

有興趣的同學可以查查相關資料呦

(67)

多項式乘法

• 把多項式表達為

• 同理:

• 順便不失一般性的假設 n+1 是 2 的次方(如果不是的話,就 加入一些係數為 0 的高次項)

為了方便之後的講解 :)

(68)

多項式乘法

• 既然是在教分治,那就先把多項式切兩半看看

• 令

• 同理

(69)

多項式乘法

• 既然是在教分治,那就先把多項式切兩半看看

• 令

• 所以,

(70)

多項式乘法

• A, B, C, D 都是 (n/2) 次的多項式

• 所以做四次比較小的乘法 & 一點加法就可以解決原問題了!

(71)

多項式乘法

• A, B, C, D 都是 (n/2) 次的多項式

• 所以做四次比較小的乘法 & 一點加法就可以解決原問題了!

• 成功切成子問題 => Divide & Conquer!

• 可是,這樣真的有比較快嗎?

(72)

多項式乘法

• A, B, C, D 都是 (n/2) 次的多項式

• 所以做四次比較小的乘法 & 一點加法就可以解決原問題了!

• 成功切成子問題 => Divide & Conquer!

• 可是,這樣真的有比較快嗎?

• 來分析一下複雜度,T(n) = 4T(n / 2) + O(n)

O(n) 是加法的部份

(73)

多項式乘法

• A, B, C, D 都是 (n/2) 次的多項式

• 所以做四次比較小的乘法 & 一點加法就可以解決原問題了!

• 成功切成子問題 => Divide & Conquer!

• 可是,這樣真的有比較快嗎?

• 來分析一下複雜度,T(n) = 4T(n / 2) + O(n)

• 用前面的教的遞迴分析,或者是 Master Theorem,

可以得到 T(n) = O(n^2)

• 沒有變快 QQQ

(74)

Karatsuba

• 我們要算 AC, AD + BC, BD

(75)

Karatsuba

• 我們要算 AC, AD + BC, BD

• 靈光一閃,如果我們計算

(76)

Karatsuba

• 我們要算 AC, AD + BC, BD

• 靈光一閃,如果我們計算

• 就可以把原本的式子化為

• 乘法只剩下三次了!

(77)

Karatsuba -- 複雜度

• 剛剛上面那個演算法,被稱做 Karatsuba Algorithm

• 我們來分析一下時間複雜度吧

(78)

Karatsuba -- 複雜度

• 剛剛上面那個演算法,被稱做 Karatsuba Algorithm

• 我們來分析一下時間複雜度吧

• 根據前面教的 Master Theorem,可以得到 T(n) 就是

(79)

Karatsuba -- 複雜度

• 剛剛上面那個演算法,被稱做 Karatsuba Algorithm

• 我們來分析一下時間複雜度吧

• 根據前面教的 Master Theorem,可以得到 T(n) 就是

• 類似的做法也有被應用在矩陣乘法上,有興趣的同學可以查查

(80)

平面最近點對

• 在平面上給你 N 個點,要你找出歐式距離最短的兩個點。

• N <= 100,000

• 練習題:https://tioj.ck.tp.edu.tw/problems/1500

、 https://codeforces.com/contest/429/problem/D

(81)

平面最近點對

• 開心 C(N, 2) = O(N^2) 當然不是我們要的

• 如果在平面上想要做 divide and conquer,該怎麼分割問 題?

(82)

平面最近點對

• 我們可以先把所有輸入的點照 x 座標排序後,在中間畫一條分 隔線。

• 這樣可能的答案就分成(兩個點都在左邊)、(兩個點都在右 邊)、(橫跨分隔線) 三種情況

• 一些平面上的 D&C 題都會做類似的事。

• 顯然只有點對「橫跨分隔線」的情況需要討論,如果這個情況可 以解決的話,其他兩個情況只要遞迴下去解就好了。

(83)

平面最近點對

• 如果只是要算分隔線兩邊的最近點對,有什麼好方法嗎?

(84)

平面最近點對

• 如果只是要算分隔線兩邊的最近點對,有什麼好方法嗎?

• 因為 x 座標的大小關係已經確立了,所以可以把兩邊直接照 y 座標排序

• 然後就發現還是好困難...

(85)

平面最近點對

• 定神一想,會發現如果遞迴下去後找到的最近點對的距離是 d

,那麼我們根本就不需要考慮那些距離超過 d 的點對

• 所以離分隔線超過 d 的點都不需要去考慮。

• 對於每個點,也只有 y 座標差距不超過 d 的點可能可以讓你 找到更近的點對

• 這樣子複雜度會是好的嗎?

• 聽起來只是個壓常數的剪枝,但在什麼情況下,這個做法一樣會 退化成 O(N^2) 呢?

(86)

平面最近點對

• 因為已經知道各自的最近點對的距離是 d ,所以每個點附近的 點不會太多!

• 附近的點只會有常數個,所以直接跑下去複雜度就是好的!

(87)

平面最近點對

• 來分析一下複雜度

• T(n) = 2T(n / 2) + O(n log n)

conquer 時要把點按照 y 座標排序

(88)

平面最近點對

• 來分析一下複雜度

• T(n) = 2T(n / 2) + O(n log n)

conquer 時要把點按照 y 座標排序

• 根據 recursion-tree 和 master theorem ,都可以得到 O(n (log n)^2)

• 注意這裡的 master theorem 要套 Case 2

(89)

平面最近點對

• 不能做到更好嗎? O(n (log n)^2) 感覺很慢

(90)

平面最近點對

• 不能做到更好嗎? O(n (log n)^2) 感覺很慢

• 靈光一閃,想起 merge sort

(91)

平面最近點對

• 不能做到更好嗎? O(n (log n)^2) 感覺很慢

• 靈光一閃,想起 merge sort

• 後面那個 O(n log n) ,可以用 merge sort 壓到 O(n)

• T(n) = 2T(n / 2) + O(n)

• T(n) = O(n log n) !

(92)

平面最近點對

• 不能做到更好嗎? O(n (log n)^2) 感覺很慢

• 靈光一閃,想起 merge sort

• 後面那個 O(n log n) ,可以用 merge sort 壓到 O(n)

• T(n) = 2T(n / 2) + O(n)

• T(n) = O(n log n) !

• 這題也有非分治的作法,有興趣可以上網查查

(93)

尋找第 k 大

• 給你一個序列,請你找到第 k 大

• 還不簡單? sort 就好啦!

• 但我希望可以做到 O(n)

(94)

尋找第 k 大

• 神仙分治想法

• 我們首先先把序列五個五個分一組,並找到每組的中位數

(95)

尋找第 k 大

• 把所有中位數蒐集起來,再找到「中位數的中位數」

怎麼再找中位數?

(96)

尋找第 k 大

• 把所有中位數蒐集起來,再找到「中位數的中位數」

怎麼再找中位數?對規模 n/5 的問題呼叫尋找第 n/10 大

(97)

尋找第 k 大

• 令剛剛找到的數字是 p,把數字分成 >p 跟 <p 兩堆

(98)

尋找第 k 大

• 令剛剛找到的數字是 p,把數字分成 >p 跟 <p 兩堆

• 注意到至少有 3n/10 個數字比 p 小、至少有 3n/10 個數字 比 p 大

(99)

尋找第 k 大

• 令剛剛找到的數字是 p,把數字分成 >p 跟 <p 兩堆

• 注意到至少有 3n/10 個數字比 p 小、至少有 3n/10 個數字 比 p 大

• 看第 k 大在哪邊,往那邊遞迴就可以了!

• 這種神仙操作到底複雜度長怎樣呢?

(100)

尋找第 k 大

• 分析複雜度:

對規模 n/5 的問題呼叫尋找第 n/10 大: T(n/5)

遞迴找 k 大: 少掉至少 3n/10 個數字 -> T(7n/10)

分組、分兩堆等等: O(n)

(101)

尋找第 k 大

• 分析複雜度:

對規模 n/5 的問題呼叫尋找第 n/10 大: T(n/5)

遞迴找 k 大: 少掉至少 3n/10 個數字 -> T(7n/10)

分組、分兩堆等等: O(n)

(102)

尋找第 k 大

• 分析複雜度:

對規模 n/5 的問題呼叫尋找第 n/10 大: T(n/5)

遞迴找 k 大: 少掉至少 3n/10 個數字 -> T(7n/10)

分組、分兩堆等等: O(n)

(103)

尋找第 k 大

• 分析複雜度:

對規模 n/5 的問題呼叫尋找第 n/10 大: T(n/5)

遞迴找 k 大: 少掉至少 3n/10 個數字 -> T(7n/10)

分組、分兩堆等等: O(n)

by 數學歸納法!

(104)

尋找第 k 大

• 分析複雜度:

對規模 n/5 的問題呼叫尋找第 n/10 大: T(n/5)

遞迴找 k 大: 少掉至少 3n/10 個數字 -> T(7n/10)

分組、分兩堆等等: O(n)

by 數學歸納法!

這東西還蠻詭異的,但真的就是線性XD

主要是想讓你們感受一下分治法的強大

(105)

總結分治

• 已經看過很多在序列、平面的題目了

• 但是其實分治還能在奇怪(?) 的地方分治

例如樹、圖等等

• 往往分治還需要搭配很多噁心的資料結構、演算法

• 分治常常會在偏難的題目中走出一條通路

• 大家加油

參考文獻

相關文件

pop

● 應用 Greedy choice,將問題劃分成子問題,根據 optimal. substructure,可以持續應用

● 應用 Greedy choice ,將問題劃分成子問題,根據 optimal su bstructure ,可以持續應用 Greedy choice

貪心 Greedy. Lecture

DP3 inclass.

Lecture by baluteshih Credit by zolution... Minimum

錯排數

課堂補充 by TreapKing modified