書籍資訊
- 書名:《圖解演算法:使用 C#》
- 作者:吳燦銘、胡昭民
- 這篇主題:整理幾種最常見的演算法思路
這篇在講什麼
這一篇不是專講某一題,而是在整理幾種解題時非常常見的套路。當題目一來,很多時候先判斷「這題像哪一類」,會比直接硬寫更有效率。
這篇主要整理了:
- 分治法
- 遞迴
- 動態規劃
- 迭代
- 回溯
- 貪心
分治法
分治法的核心精神是把一個大問題拆成幾個相似的小問題,分別解完之後再合併結果。
它通常會經過三步:
- 分割問題
- 解決子問題
- 合併答案
這種方法適合子問題彼此相對獨立,而且合併規則清楚的情況。像是合併排序、快速排序,都是很典型的例子。
遞迴
遞迴就是函式呼叫自己。寫遞迴時最重要的是兩件事:
- 什麼時候停止
- 每一層怎麼往更小的問題前進
如果這兩件事沒先想清楚,遞迴通常不是難讀,就是直接失控。
遞迴很適合處理有明顯層次或樹狀結構的問題,例如:
- 樹的走訪
- 分治問題
- 數學定義本身就具遞推性
動態規劃
動態規劃處理的是「重複子問題」。如果同一批中間結果會被反覆用到,就可以把它們存下來,避免重算。
它的核心通常是:
- 定義狀態
- 找出狀態轉移
- 記錄已算過的結果
和單純遞迴相比,DP 的差異不在於有沒有拆子問題,而在於有沒有系統性地重用答案。
迭代
有些問題不一定要用遞迴,改用迴圈一步一步往前推,反而更直接也更好控制。
迭代常見的優點是:
- 邏輯比較平鋪直敘
- 比較容易觀察變數變化
- 不會有呼叫堆疊過深的問題
很多遞迴解,其實都可以改寫成迭代解,差別只在於狀態是放在系統堆疊裡,還是你自己手動管理。
回溯
回溯可以看成一種有策略的暴力搜尋。先嘗試一條路,如果走不通,就退回上一步改試別條路。
它常出現在:
- 排列組合
- 迷宮問題
- N 皇后
- 列舉所有可行解
回溯的關鍵不只是「試」,而是要知道什麼時候應該撤退,以及怎麼避免無效搜尋。
貪心
貪心法的做法是每一步都先選當下看起來最好的方案,希望一路累積成全域最佳解。
它的好處是:
- 實作通常簡潔
- 效率常常不錯
但限制也很明顯:
- 局部最佳不一定能推出整體最佳
所以貪心法能不能成立,核心不是寫起來順不順,而是你能不能證明這個選擇策略是正確的。
我自己的整理
這篇其實很像演算法工具箱的索引。遇到新題目時,可以先這樣想:
- 能不能自然拆成小問題:想分治
- 有沒有明顯層次結構:想遞迴
- 子問題會不會重複:想 DP
- 可不可以穩定地一步步推:想迭代
- 需不需要枚舉所有可能:想回溯
- 能不能證明局部最佳會導向全域最佳:想貪心
這種分類不一定一次就判斷正確,但至少能讓找解法的方向更快收斂。
先記住的重點
- 分治重點在拆分與合併
- 遞迴一定要先想 base case 和縮小方向
- 動態規劃的核心是重複子問題與結果重用
- 回溯是試錯式搜尋,但要有明確的退回機制
- 貪心要成立,前提是選擇策略可以被證明