分析教材用最大子段和展示了一次分治,遞迴教材列出了合併排序與快速排序,但沒有把「遞迴式怎麼解」收成可以套用的定理。本篇補上替換法的一個完整例子、遞迴樹的直覺,以及主定理的三個標準情況。

相關教材:Chapter2_Algorithm_Analysis_Teaching_Materials.md、Recursion_Teaching_Materials.md、Sorting_Algorithms_Teaching_Materials.md。


目錄

  1. 分治的三步
  2. 遞迴式從哪裡來
  3. 替換法
  4. 遞迴樹
  5. 主定理
  6. 三個不能直接套的例子
  7. 計數逆序對
  8. 常見陷阱
  9. 練習題

1. 分治的三步

  1. 分割:把大小為 (n) 的問題切成若干個較小的同類問題。
  2. 解決:子問題小到可以直接算;否則遞迴。
  3. 合併:把子問題的答案合成原問題的答案。

動態規劃和它的差別在於子問題是否重疊。分治的左右兩半不該依賴彼此的中間結果以外的重複計算。若同一題被問很多次,改看 DP 教材。


2. 遞迴式從哪裡來

合併排序把陣列切成兩半,兩邊各做一次,再花 (\Theta(n)) 合併:

[ T(n) = 2T(n/2) + \Theta(n), \quad T(1) = \Theta(1) ]

一般形式是 (a) 個子問題,每個是原來的 (1/b),合併成本 (f(n)):

[ T(n) = a\,T(n/b) + f(n) ]

(a \ge 1)、(b > 1)。快速排序的最壞情況不是這個形狀(子問題大小是 (n-1) 和 (0)),所以主定理管不到那個最壞情況。它的平均情況需要別的論證。


3. 替換法

猜一個上界,再用歸納法證明。

猜 (T(n) \le cn\log_2 n) 能滿足 (T(n) = 2T(n/2) + n)(先把 (\Theta(n)) 寫成 (n),底數換掉只影響常數)。

[ T(n) \le 2\cdot c\cdot\frac{n}{2}\log_2\frac{n}{2} + n = cn(\log_2 n - 1) + n = cn\log_2 n - cn + n ]

要 (\le cn\log_2 n),需要 (-cn + n \le 0),也就是 (c \ge 1)。基底 (n=2) 時單獨檢查常數是否夠大。

替換法的困難是「猜」。遞迴樹用來產生那個猜。


4. 遞迴樹

(T(n) = 2T(n/2) + n) 的樹:

  • 第 0 層成本 (n)
  • 第 1 層兩個節點,各 (n/2),合計 (n)
  • 第 (i) 層 (2^i) 個節點,各 (n/2^i),合計仍是 (n)
  • 約 (\log_2 n) 層

總成本 (n\log_2 n)。這和替換法的猜一致。

若是 (T(n) = 2T(n/2) + n^2):第 (i) 層合計 (2^i \cdot (n/2^i)^2 = n^2 / 2^i)。這是等比級數,根的 (n^2) 佔主導,總和 (\Theta(n^2))。

葉子有多少:深度 (\log_b n),葉子數 (a^{\log_b n} = n^{\log_b a})。葉子貢獻 (\Theta(n^{\log_b a}))。主定理就是在比「葉子」和「內部合併成本」誰比較大。


5. 主定理

令 (T(n) = aT(n/b) + f(n)),(c_{\mathrm{crit}} = \log_b a)。比較 (f(n)) 和 (n^{c_{\mathrm{crit}}})。

情況 1。 (f(n) = O(n^{c_{\mathrm{crit}} - \varepsilon})),(\varepsilon > 0)。葉子比合併貴。

[ T(n) = \Theta(n^{\log_b a}) ]

情況 2。 (f(n) = \Theta(n^{c_{\mathrm{crit}}} \log^k n)),(k \ge 0)。每一層(再乘上對數的次方)一樣重。

[ T(n) = \Theta(n^{\log_b a} \log^{k+1} n) ]

(k=0) 就是最常見的 (\Theta(n^{\log_b a}\log n))。合併排序是 (a=2,b=2,f(n)=\Theta(n)),(c_{\mathrm{crit}}=1),(k=0),所以 (T(n)=\Theta(n\log n))。

情況 3。 (f(n) = \Omega(n^{c_{\mathrm{crit}}+\varepsilon})),而且對足夠大的 (n) 有正規條件 (a f(n/b) \le c f(n)),其中常數 (c<1)。根的合併比所有葉子貴。

[ T(n) = \Theta(f(n)) ]

(T(n)=2T(n/2)+n^2):(c_{\mathrm{crit}}=1),(f=n^2) 多出一個多項式因子。正規條件 (2\cdot(n/2)^2 = n^2/2 \le c n^2) 對 (c=1/2) 成立。所以 (T(n)=\Theta(n^2))。


6. 三個不能直接套的例子

  1. 差距不是多項式。 (f(n) = n\log n)、(a=2)、(b=2) 時,(f(n)/n = \log n) 比任何 (n^{\varepsilon}) 都慢,也不是 (\Theta(1))。它落在情況 2 的 (k=1):(T(n)=\Theta(n\log^2 n))。若只背「三個情況」卻忘了 (\log^k),會以為定理失靈。
  2. 子問題大小差很遠。 (T(n)=T(n-1)+T(n/2)+n) 不是 (aT(n/b))。用遞迴樹或 Akra–Bazzi,不要硬套。
  3. 快速排序最壞。 (T(n)=T(n-1)+\Theta(n)=\Theta(n^2)),主定理的 (b) 必須是大於 1 的常數比例,(n-1) 不是 (n/b)。

7. 計數逆序對

逆序對是 (ia_j)。分治和合併排序同一棵遞迴:

  • 左半的逆序對,遞迴。
  • 右半的逆序對,遞迴。
  • 跨左右的逆序對:合併時,若右邊的 (y) 先被取出,則左半還沒取出的每一個都和 (y) 形成逆序對。

合併仍是 (\Theta(n)),遞迴式與合併排序相同,所以 (O(n\log n))。二重迴圈是 (O(n^2))。

例:[2, 4, 1, 3]。

  • 左 [2,4] 逆序對 0;右 [1,3] 逆序對 0。
  • 合併:取出 1 時左半還有 2,4,貢獻 2;取出 2;取出 3 時左半還有 4,貢獻 1。
  • 跨邊 3 對:(2,1), (4,1), (4,3)。總數 3。

8. 常見陷阱

  • 把底數當成要背的常數。 (\log_b a) 的底是子問題縮小的倍率 (b),不是 2。(a=3,b=2) 時臨界指數是 (\log_2 3 \approx 1.585)。
  • 情況 3 忘了正規條件。 多項式都滿足;人為造出的 (f) 可能在子問題上突然變大,定理不適用。
  • 地板與天花板。 (n/2) 寫成 (\lfloor n/2\rfloor) 不改變主定理的結論,歸納時會多出一堆低階項,替換法要把那些項吸收進常數。
  • 把主定理用在空間。 合併排序的額外空間是 (\Theta(n)),不是 (n\log n)。時間的遞迴式和空間的遞迴式要分開寫。

9. 練習題

  1. (T(n)=8T(n/2)+n^2)。屬於哪一種情況?答案的階是什麼?
  2. (T(n)=2T(n/2)+n\log n)。(k) 是多少?
  3. 為什麼二元搜尋的 (T(n)=T(n/2)+\Theta(1)) 是 (\Theta(\log n)),而不是 (\Theta(n))?
  4. 用手算 [3, 1, 2] 的逆序對,並標出哪些是跨邊產生的。
  5. Strassen 矩陣乘法是 (T(n)=7T(n/2)+\Theta(n^2))。它比直接的 (\Theta(n^3)) 好在哪一個指數?

參考答案

  1. (c_{\mathrm{crit}}=\log_2 8=3),(f(n)=n^2 = O(n^{3-\varepsilon})),情況 1,(T(n)=\Theta(n^3))。
  2. (c_{\mathrm{crit}}=1),(f(n)=\Theta(n\log^1 n)),所以 (k=1),(T(n)=\Theta(n\log^2 n))。
  3. (a=1,b=2),(c_{\mathrm{crit}}=0),(f(n)=\Theta(1)=\Theta(n^0)),情況 2 且 (k=0),(T(n)=\Theta(\log n))。只有一個子問題,葉子只有一片,成本來自 (\log n) 層的常數工作。
  4. 逆序對是 (3,1), (3,2),共 2。左 [3]、右 [1,2] 內部都是 0;兩對都是跨邊。
  5. (c_{\mathrm{crit}}=\log_2 7 \approx 2.807),(n^2) 屬於情況 1,所以 (T(n)=\Theta(n^{\log_2 7})),指數小於 3。

小結

分治的時間由 (T(n)=aT(n/b)+f(n)) 決定。先看 (n^{\log_b a}) 和 (f(n)) 誰大:葉子主導、每一層打平、或根的合併主導。合併排序、二元搜尋、一層 (n^2) 的分治分別對上這三種。子問題不是固定比例縮小時,不要套主定理。逆序對說明分治的合併步驟可以順便做比較排序以外的工作,複雜度仍跟合併排序一樣。