資工研究所常見演算法時間複雜度整理
資工研究所常見演算法時間複雜度整理
版本:2026-09-09
語言:繁體中文(zh-TW)
定位:資工研究所入學考、演算法/資料結構課程、口試與複習速查
主要依據:CLRS、原始論文、Princeton Algorithms、MIT OpenCourseWare、CP-Algorithms、GeeksforGeeks;中文資源列於文末供交叉複習。
Executive Summary
這份整理的核心不是只背一張 Big-O 表,而是辨認「複雜度成立的前提」。同一個演算法可能因資料表示、輔助資料結構、輸入分布、是否允許提早停止、字母表大小,甚至雜湊碰撞模型而有不同界限。研究所考題常用這些前提製造選項差異,因此表格同時標示最佳/平均/最壞、輔助空間、穩定性、in-place 與使用條件。
最值得優先記憶的骨架如下:
- 比較式排序下界:一般 comparison sort 的最壞情況需要 (\Omega(n\log n)) 次比較;Merge Sort 與 Heap Sort 保證 (O(n\log n)),Quick Sort 平均/期望 (O(n\log n)) 但最壞 (O(n^2))。Counting/Radix/Bucket 不只靠元素間比較,因此可在額外假設下突破 (n\log n)。
- 圖論先看邊權與圖密度:BFS/DFS 是 (O(V+E));Dijkstra 適用非負邊權,binary heap 典型為 (O((V+E)\log V));Bellman-Ford 可處理負邊並偵測負環,最壞 (O(VE));Floyd-Warshall 以 (O(V^3)) 換取 all-pairs shortest paths;Kruskal 常見 (O(E\log E)),Prim 依實作為 (O(E\log V)) 或 dense graph 的 (O(V^2))。
- 動態規劃要先辨識狀態維度:0/1 Knapsack 的 (O(nW)) 是 pseudo-polynomial;LCS 的標準 DP 為 (O(mn));Matrix Chain Multiplication 是 (O(n^3)) 時間、(O(n^2)) 空間。
- 字串演算法重點在 preprocessing + query:KMP 與 Z-algorithm 可線性處理;Rabin-Karp 的期望時間很好,但若每次 hash 命中都做字串驗證,最壞可退化;Suffix Array 常見 doubling 建構為 (O(n\log n)),Suffix Tree 在固定/可線性處理字母表的 Ukkonen 類演算法下可 (O(n)) 建構。
- 資料結構要分 operation:Hash Table 的查找/插入/刪除通常是 expected (O(1)) 但最壞 (O(n));Union-Find 配合 path compression + union by rank/size 為 amortized (O(\alpha(n)));Segment Tree 與 Fenwick Tree 典型更新/查詢是 (O(\log n));Bloom Filter 固定 (k) 個 hash 時插入與查詢為 (O(k)),以 false positive 換取極省空間。
本報告另外補入研究所與核心課程常見的 SCC、Edmonds-Karp、Dinic、LIS、Aho-Corasick、Manacher、Binary Heap、Sparse Table。這些主題能補足「連通性/最大流/進階 DP/多模式字串/回文/優先佇列/靜態 RMQ」等常見考點。CLRS、MIT-Algorithms 與台大資訊系統訓練班的課程範圍亦可看出排序、搜尋、DP、BFS/DFS、MST、最短路與網路流是典型核心內容。NTU-Training
記號、假設與判讀原則
記號
| 符號意義 | |
|---|---|
| (n) | 一般輸入大小/元素數 |
| (V), (E) | 圖的頂點數、邊數 |
| (m) | 第二字串長度,或依上下文明定的模式總長 |
| (W) | Knapsack 容量 |
| (K) | Counting Sort 的鍵值範圍大小 |
| (D) | Radix Sort 的位數 |
| (B) | radix/bucket 的桶數或基底 |
| (\Sigma) | 字母表大小 |
| (L) | Trie 單一 key/字串長度 |
| (b), (d) | A* 的 branching factor 與解的深度 |
| (\alpha(n)) | inverse Ackermann function,實務上極慢成長 |
| (k_h) | Bloom Filter 使用的 hash function 數量 |
occ |
字串匹配輸出的 occurrence 數 |
空間複雜度口徑
除非另註,本表的「空間」指 auxiliary space(演算法額外工作空間),不把輸入本身重複計入。圖演算法若必須建立 residual graph、transpose graph 或大型 distance matrix,會明確寫出。Python 範例以可讀性為主,實際常數與某些容器的額外配置不等於理論模型。
最佳/平均/最壞不一定都有自然定義
「平均」必須依賴輸入機率模型;若沒有標準且明確的分布,本報告不硬造一個平均值,而寫「與輸入/heuristic 有關」或使用標準 worst-case upper bound。BFS/DFS 若定義為完整 traversal,三種情況皆為 (\Theta(V+E));若題目改成「找到某一 target 就停」,才可能有 (\Theta(1)) 的最佳情況。CP-BFS
穩定與 in-place 的適用範圍
「穩定(stable)」主要是排序性質:相等 key 的相對順序是否保持。「in-place」也最常用於排序;對圖論、DP、字串 index 等演算法,表中以「不適用」或直接說明工作空間,避免把不同概念混在一起。
演算法分類圖
flowchart TD
A[資工研究所常見演算法與資料結構]
A --> S[排序與搜尋]
A --> G[圖論]
A --> D[動態規劃/分治]
A --> T[字串]
A --> X[資料結構/機率式結構]
S --> S1[Comparison Sort]
S --> S2[Non-comparison Sort]
S --> S3[Linear / Binary Search]
G --> G1[Traversal: BFS / DFS]
G --> G2[Shortest Path: Dijkstra / Bellman-Ford / Floyd / A*]
G --> G3[MST: Kruskal / Prim]
G --> G4[DAG / SCC / Max Flow]
D --> D1[Knapsack / LCS / MCM / LIS]
T --> T1[KMP / Rabin-Karp / Z]
T --> T2[Trie / Aho-Corasick]
T --> T3[Suffix Array / Suffix Tree / Manacher]
X --> X1[Hash Table / Bloom Filter]
X --> X2[Union-Find]
X --> X3[Segment / Fenwick / Sparse Table]
X --> X4[Binary Heap]
核心複雜度總表
排序與搜尋
排序表中的「空間」為 auxiliary space。Quick Sort 的 in-place 是指 partition 通常原地,但 recursion stack 仍要空間。Bucket Sort 的平均界需要接近均勻分布等假設;Radix Sort 需要每一位使用穩定的子排序才能保證整體 LSD radix 的穩定性。
| 演算法 | 最佳時間 | 平均/期望時間 | 最壞時間 | 空間 | 穩定 | In-place | 適用情境與註解 |
|---|---|---|---|---|---|---|---|
| Bubble Sort | (\Theta(n)) GFG-Sort | (\Theta(n^2)) GFG-Sort | (\Theta(n^2)) GFG-Sort | (O(1)) GFG-Sort | 是 | 是 | 教學、近乎排序且資料很小;需有「一輪無交換即停止」最佳才是線性。 |
| Insertion Sort | (\Theta(n)) GFG-Sort | (\Theta(n^2)) GFG-Sort | (\Theta(n^2)) GFG-Sort | (O(1)) GFG-Sort | 是 | 是 | 小資料、近乎有序資料、hybrid sort 的小區段;adaptive。 |
| Selection Sort | (\Theta(n^2)) GFG-Sort | (\Theta(n^2)) GFG-Sort | (\Theta(n^2)) GFG-Sort | (O(1)) GFG-Sort | 否(標準版) | 是 | 比較次數固定,但交換次數少;寫入成本昂貴時偶有價值。 |
| Merge Sort | (\Theta(n\log n)) GFG-Sort | (\Theta(n\log n)) GFG-Sort | (\Theta(n\log n)) GFG-Sort | (O(n)) GFG-Sort | 是 | 否(標準 array 版) | 需要穩定排序、linked list、external sorting;worst-case 有保證。 |
| Quick Sort | (\Theta(n\log n)) Princeton-Quick | (\Theta(n\log n)) expected Princeton-Quick | (\Theta(n^2)) Princeton-Quick | 平均 (O(\log n)),最壞 (O(n)) stack GFG-Sort | 否 | 是(partition) | 實務常快、cache locality 佳;random pivot/shuffle 可避免固定惡劣輸入。 |
| Heap Sort | (\Theta(n\log n)) GFG-Sort | (\Theta(n\log n)) GFG-Sort | (\Theta(n\log n)) GFG-Sort | (O(1)) Princeton-Heap | 否 | 是 | 要 worst-case (n\log n) 且只用常數額外空間;cache locality 通常不如 quicksort。 |
| Counting Sort | (\Theta(n+K)) GFG-Sort-Analysis | (\Theta(n+K)) GFG-Sort-Analysis | (\Theta(n+K)) GFG-Sort-Analysis | (O(n+K))(穩定標準版) GFG-Sort-Analysis | 是(標準版) | 否 | 整數 key 且範圍 (K) 不大;不是 comparison sort。 |
| Radix Sort | (\Theta(D(n+B))) GFG-Radix | (\Theta(D(n+B))) GFG-Radix | (\Theta(D(n+B))) GFG-Radix | (O(n+B)) GFG-Radix | 條件式(每一位要穩定) | 否(標準 LSD) | 固定位數整數、ID、字串;基底與 digit extractor 影響常數。 |
| Bucket Sort | (\Theta(n+B)) GFG-Sort-Analysis | (\Theta(n+B))(均勻分布假設) GFG-Sort-Analysis | (O(n^2+B)) GFG-Sort-Analysis | (O(n+B)) GFG-Sort-Analysis | 條件式 | 通常否 | 已知分布且元素可均勻散入桶;全落同桶會退化。 |
| Linear Search | (\Theta(1)) GFG-Linear | (\Theta(n)) GFG-Linear | (\Theta(n)) GFG-Linear | (O(1)) GFG-Linear | — | 是 | 未排序序列、一次性查找、資料很小。 |
| Binary Search | (\Theta(1)) GFG-Binary | (\Theta(\log n)) GFG-Binary | (\Theta(\log n)) CP-Binary | iterative (O(1)) GFG-Binary | — | 是 | 必須有單調性/已排序;研究所常考 lower_bound、upper_bound、binary search on answer。 |
圖論
除 A* 外,表格以「完成所述標準任務」為主。Dijkstra 的界取 adjacency list + binary heap;Prim 同時列 sparse/dense 版本。A* 無法在不指定 heuristic 與 state space 的情況下給一個普遍且有意義的「平均時間」。
| 演算法 | 最佳時間 | 平均/常用界 | 最壞時間 | 空間 | 穩定 | In-place | 適用情境與註解 |
|---|---|---|---|---|---|---|---|
| BFS | (\Theta(V+E))(完整 traversal) CP-BFS | (\Theta(V+E)) CP-BFS | (\Theta(V+E)) CP-BFS | (O(V)) auxiliary GFG-BFS-Space | — | 不適用 | 無權圖/等權圖最短路、層次、連通性。若找到 target 即停,最佳可降至 (O(1))。 |
| DFS | (\Theta(V+E))(完整 traversal) CP-DFS | (\Theta(V+E)) CP-DFS | (\Theta(V+E)) CP-DFS | (O(V)) visited + recursion/stack CP-DFS | — | 不適用 | 拓樸、cycle、SCC、橋、割點與 backtracking 的核心。 |
| Dijkstra(binary heap) | 標準 upper bound (O((V+E)\log V)) CP-Dijkstra | (O((V+E)\log V)) CP-Dijkstra | (O((V+E)\log V)) CP-Dijkstra | (O(V+E))(lazy heap 可存重複 entry) CP-Dijkstra | — | 不適用 | 僅非負邊權的 SSSP;dense graph 可改用 (O(V^2)) 實作。 |
| Bellman-Ford(含 early stop) | (O(E)) GFG-Bellman | 通常以 (O(VE)) upper bound 表示 GFG-Bellman | (O(VE)) CP-Bellman | (O(V)) GFG-Bellman | — | 不適用 | 可處理負邊並偵測可達負環;比 Dijkstra 慢。 |
| Floyd-Warshall | (\Theta(V^3)) CP-Floyd | (\Theta(V^3)) CP-Floyd | (\Theta(V^3)) CP-Floyd | (\Theta(V^2)) GFG-Shortest | — | 可覆寫 distance matrix | All-pairs shortest paths;實作簡潔,適合 (V) 不大或圖較 dense。 |
| A* | (O(1))(start 已是 goal) | 依 heuristic、tie-breaking 與 state space;無單一一般平均界 AStar-Original | 常以 implicit tree (O(b^d)) 表示;有限顯式圖的 heap 實作常見 (O(E\log V)) upper bound GFG-Shortest | 常可達 (O(b^d)) states AStar-Complexity | — | 不適用 | (f(n)=g(n)+h(n));admissible heuristic 保證 tree-search 型最適性,consistent heuristic 對 graph search 特別重要。 |
| Kruskal | (O(E\log E)) CP-Kruskal | (O(E\log E)) CP-Kruskal | (O(E\log E)) CP-Kruskal | (O(V)) DSU + sort implementation CP-Kruskal | — | 不適用 | MST;對 sparse graph 直觀有效。排序後靠 Union-Find 判斷是否成環。 |
| Prim(binary heap) | 標準 upper (O(E\log V)) CP-Prim | (O(E\log V)) CP-Prim | (O(E\log V)) CP-Prim | (O(V+E)) CP-Prim | — | 不適用 | MST;adjacency matrix 版本 (O(V^2)) 對 dense graph 很有競爭力。 |
| Topological Sort | (\Theta(V+E)) GFG-Topo | (\Theta(V+E)) GFG-Topo | (\Theta(V+E)) GFG-Topo | (O(V)) GFG-Topo | — | 不適用 | 僅 DAG 有完整拓樸序;Kahn 可藉處理頂點數偵測 cycle,DFS 亦可。 |
| SCC(Kosaraju/Tarjan) | (\Theta(V+E)) CP-SCC | (\Theta(V+E)) CP-SCC | (\Theta(V+E)) CP-SCC | (O(V)) auxiliary;Kosaraju 若顯式建 transpose 再加 (O(V+E)) CP-SCC | — | 不適用 | Directed graph condensation、2-SAT、cycle structure。 |
| Edmonds-Karp | upper (O(VE^2)) CP-EdmondsKarp | 通常以 worst-case upper bound 表示 CP-EdmondsKarp | (O(VE^2)) CP-EdmondsKarp | (O(V+E)) residual graph CP-EdmondsKarp | — | 不適用 | Maximum flow;Ford-Fulkerson 每次用 BFS 找最短 augmenting path,易證明但較慢。 |
| Dinic | 依圖類型;general upper (O(V^2E)) CP-Dinic | general (O(V^2E)) upper CP-Dinic | (O(V^2E)) CP-Dinic | (O(V+E)) CP-Dinic | — | 不適用 | Maximum flow;level graph + blocking flow。unit network 可有更佳界。 |
動態規劃與分治/序列
| 演算法 | 最佳時間 | 平均/常用界 | 最壞時間 | 空間 | 穩定 | In-place | 適用情境與註解 |
|---|---|---|---|---|---|---|---|
| 0/1 Knapsack DP | (\Theta(nW))(標準 tabulation) CP-Knapsack | (\Theta(nW)) CP-Knapsack | (\Theta(nW)) CP-Knapsack | (O(W)) 可壓縮 CP-Knapsack | — | 否 | 容量型 DP;(W) 是數值而非輸入 bit-length,所以稱 pseudo-polynomial。 |
| Longest Common Subsequence | (\Theta(mn))(標準 DP) GFG-LCS | (\Theta(mn)) GFG-LCS | (\Theta(mn)) GFG-LCS | (O(mn)),只求長度可壓到 (O(\min(m,n))) GFG-LCS | — | 否 | diff、序列相似度、經典二維 DP;回溯序列通常需保留較多資訊。 |
| Matrix Chain Multiplication | (\Theta(n^3)) GFG-MCM | (\Theta(n^3)) GFG-MCM | (\Theta(n^3)) GFG-MCM | (\Theta(n^2)) GFG-MCM | — | 否 | interval DP 經典題:最佳括號化只改乘法順序,不改矩陣結果。 |
| Longest Increasing Subsequence(binary-search / patience 思路) | (O(n\log n)) CP-LIS | (O(n\log n)) CP-LIS | (O(n\log n)) CP-LIS | (O(n)) CP-LIS | — | 否 | 研究所常見序列題;只求長度可用 tails 陣列,若要還原需 predecessor 資訊。 |
字串演算法與索引
| 演算法 | 最佳時間 | 平均/期望時間 | 最壞時間 | 空間 | 穩定 | In-place | 適用情境與註解 |
|---|---|---|---|---|---|---|---|
| KMP | (O(m)) preprocessing;搜尋可很早命中 CP-KMP | (\Theta(n+m)) full scan KMP-Original | (\Theta(n+m)) CP-KMP | (O(m)) prefix/failure table CP-KMP | — | 不適用 | 單 pattern exact matching;失配時不回退 text pointer。 |
| Rabin-Karp | (O(n+m))(hash 無大量碰撞) CP-RK | expected (O(n+m)) CP-RK | (O(nm))(反覆碰撞+逐字驗證) RK-Original | (O(1)) rolling-hash auxiliary(單 pattern) CP-RK | — | 不適用 | 多 pattern、rolling hash、查重;理論與實作都要考慮 collision。 |
| Z-algorithm | (\Theta(n)) CP-Z | (\Theta(n)) CP-Z | (\Theta(n)) CP-Z | (O(n)) Z array CP-Z | — | 不適用 | 計算每位置與 prefix 的 LCP;可做 pattern matching、periodicity。 |
| Trie | 最佳 (O(1))(首字即失配) Princeton-Trie | (O(L)) Princeton-Trie | (\Theta(L)) Princeton-Trie | (O(\text{總字元/節點數})),dense child array 可乘 (|\Sigma|) Princeton-Trie | — | 不適用 | prefix query、autocomplete、dictionary;速度與 key 長度相關而非 key 數量。 |
| Aho-Corasick | 建構 (O(M|\Sigma|))(dense transition 版) CP-AC | 掃描 (O(n+\text{occ}))(標準 automaton) CP-AC | (O(M|\Sigma|+n+\text{occ})) CP-AC | (O(M|\Sigma|)) dense transition CP-AC | — | 不適用 | 多 pattern 同時搜尋;Trie + failure links,可視為 KMP 的多模式推廣。 |
| Manacher | (\Theta(n)) CP-Manacher | (\Theta(n)) CP-Manacher | (\Theta(n)) CP-Manacher | (O(n)) CP-Manacher | — | 不適用 | 一次求所有奇/偶中心回文半徑;longest palindromic substring 經典線性解。 |
| Suffix Array(doubling) | (O(n\log n)) CP-SA | (O(n\log n)) CP-SA | (O(n\log n)) CP-SA | (O(n)) working arrays CP-SA | — | 不適用 | 全文索引、substring query、LCP;Manber-Myers 類方法典型 (O(n\log n)),另有線性建構演算法。 |
| Suffix Tree(Ukkonen 類) | (O(n))(固定/可常數處理 alphabet) Ukkonen | (O(n)) under stated alphabet model Ukkonen | (O(n)) under stated alphabet model;map children 時可成 (O(n\log |\Sigma|)) CP-ST | (O(n)) CP-ST | — | 不適用 | substring query 可 (O(m));功能強但實作複雜、常數與記憶體大。 |
資料結構與機率式結構
這一類的「最佳/平均/最壞」多半針對主要 operation,而非一次「完整演算法」。資料結構的建構時間另寫在註解中。
| 結構/演算法 | 最佳時間 | 平均/攤銷 | 最壞時間 | 空間 | 穩定 | In-place | 適用情境與註解 |
|---|---|---|---|---|---|---|---|
| Hash Table ops | (\Theta(1)) GFG-Hash | expected (\Theta(1)) GFG-Hash | (O(n)) GFG-Hash | (O(n)) GFG-Hash | — | 不適用 | 查找/插入/刪除;最壞來自大量 collision 或不良 hash。 |
| Union-Find / DSU | (O(1)) 可出現在已壓縮路徑 CP-DSU | amortized (O(\alpha(n))) CP-DSU | 單次操作可達 (O(\log n));序列攤銷近常數 CP-DSU | (O(n)) CP-DSU | — | 不適用 | dynamic connectivity、Kruskal;關鍵是 path compression + union by rank/size。 |
| Segment Tree | 某些整段 query 可 (O(1)) CP-Segment | query/update (O(\log n)) CP-Segment | query/update (O(\log n)) CP-Segment | (O(n))(常見配置約 (4n) nodes) CP-Segment | — | 不適用 | 動態 range sum/min/max、lazy propagation;build (O(n))。 |
| Fenwick Tree / BIT | 特殊 index 可少於 (\log n) 步 CP-Fenwick | prefix query/update (O(\log n)) CP-Fenwick | (O(\log n)) CP-Fenwick | (O(n)) CP-Fenwick | — | 不適用 | prefix/range sum、frequency;比 Segment Tree 短小,操作類型較受限。 |
| Bloom Filter | (\Theta(k_h)) GFG-Bloom | (\Theta(k_h)) GFG-Bloom | (\Theta(k_h)) GFG-Bloom | (\Theta(m_{\text{bits}})) Bloom-Original | — | 不適用 | 空間效率極高的 membership test;classic Bloom 有 false positive、無 false negative,標準版不直接刪除。 |
| Binary Heap | peek (\Theta(1)) Princeton-Heap | insert / extract (O(\log n)) Princeton-Heap | insert / extract (O(\log n)) Princeton-Heap | (O(n)) 儲存;heapify 可原地 Princeton-Heap | — | 是(array heap) | Priority Queue、Dijkstra、Prim、Heap Sort;bottom-up heapify 為 (O(n))。 |
| Sparse Table | query (\Theta(1))(idempotent RMQ) CP-Sparse | query (\Theta(1)) CP-Sparse | query (\Theta(1)) CP-Sparse | (O(n\log n)) CP-Sparse | — | 否 | 靜態 RMQ/GCD;preprocess (O(n\log n)),若資料更新就不適合。 |
跨類型比較與考試重點
不要把 (O(n\log n)) 當成所有排序的鐵律
比較式排序的決策樹模型有 (\Omega(n\log n)) 下界,但 Counting、Radix、Bucket 利用 key 的結構或分布,不在純 comparison model 內。因此考題若問「能否比 (n\log n) 更快」,第一步是看 key 是否為有限範圍整數、固定位數或可合理分桶,而不是直接回答「不可能」。CLRS
Quick Sort 與 Merge Sort 的核心差別不是只有平均速度
Quick Sort 的常見優勢是原地 partition 與 cache locality,但 worst case 為 (O(n^2));Merge Sort 保證 (O(n\log n)) 且穩定,但 array 版通常要 (O(n)) 額外空間。若題目指定「穩定」、「worst-case guarantee」、「external sort」或「linked list」,答案往往會改變。Princeton-Quick GFG-Sort
最短路題先做三個判斷
先問「有沒有負邊?」、「單源還是全點對?」、「圖 sparse 還是 dense?」。非負邊單源通常優先 Dijkstra;有負邊且需要偵測負環可用 Bellman-Ford;頂點數不大、需要 all-pairs 時 Floyd-Warshall 很直接。A* 則是在有目標點且有好 heuristic 的情況下,用搜尋方向性換取實務效率,而不是一個可脫離 heuristic 談固定平均 Big-O 的魔法版 Dijkstra。CP-Dijkstra CP-Bellman CP-Floyd AStar-Original
看到 (O(nW)) 要想到 pseudo-polynomial
0/1 Knapsack 的 (W) 是容量的「數值」。若 (W) 用二進位輸入,只需要 (\log W) bits 表示,因此 (O(nW)) 並不是 input bit-length 的 polynomial time。這是研究所演算法與計算複雜度題很常見的觀念陷阱。CP-Knapsack
Hash Table 的 (O(1)) 通常是 expected,而不是絕對 worst-case
若 collision 集中,chaining 可能退化成線性掃描;open addressing 也可能因 probe sequence 變長而明顯退化。因此「Hash 查找永遠 (O(1))」是錯誤敘述。實務還要考慮 load factor、resize 的 amortization 與 hash function 品質。GFG-Hash MIT-Algorithms
Union-Find 的 (\alpha(n)) 是「操作序列的攤銷界」
Path compression 與 union by rank/size 合用時,每次操作的 amortized complexity 為 (O(\alpha(n))),但不表示每個單獨 find 都嚴格是 (O(1))。考題看到「amortized」、「path compression」、「rank」時應特別敏感。CP-DSU
A* 的 Big-O 必須連同模型一起寫
A* 的展開節點數高度依賴 heuristic 品質。對 implicit state-space,常用 branching factor (b) 與 solution depth (d) 描述時間/空間可能到 (O(b^d));對有限顯式圖,以 priority queue 實作時也常看到 (O(E\log V)) 類上界。兩種寫法回答的是不同模型,不能直接互相否定。AStar-Original GFG-Shortest
附錄:逐項說明、例子與簡短程式碼
以下 Python 片段以「展示核心機制」為主,省略輸入驗證與工程化最佳化。每段程式碼皆可獨立理解;若程式碼刻意使用教學版而不達表中最強理論界,會明確註記。
Bubble Sort
相鄰元素逆序就交換,每一輪把目前最大元素推到尾端。例:[3, 1, 2] → [1, 2, 3]。有 swapped 提早終止時,已排序輸入只需一輪。
1 | def bubble_sort(a): |
Insertion Sort
維持左側 prefix 已排序,把新元素往左插到適當位置。對「幾乎排序」資料很有效,也常被 Timsort、introspective/hybrid 實作拿來處理小區段。
1 | def insertion_sort(a): |
Selection Sort
第 (i) 輪從 suffix 找最小值,與 a[i] 交換。無論輸入是否已排序都要做約 (n(n-1)/2) 次比較,但交換次數最多 (n-1)。
1 | def selection_sort(a): |
Merge Sort
分成兩半遞迴排序,再線性 merge。例:[4,1,3,2] 分成 [4,1]、[3,2],各自排序後合併。
1 | def merge_sort(a): |
Quick Sort
選 pivot,partition 成較小與較大部分再遞迴。教學版下方用額外 list 以突出概念;實際「in-place quicksort」會改用 Lomuto/Hoare partition,因此表中空間界以原地 partition + recursion stack 計。
1 | def quick_sort(a): |
Heap Sort
先 bottom-up 建 max-heap,再反覆把 root 與尾端交換並縮小 heap。理論上可原地、worst-case (O(n\log n))。
1 | def heap_sort(a): |
Counting Sort
先計數,再用 prefix sums 決定輸出位置。適合 key 位於小範圍整數 [0, K];若 (K \gg n),額外空間與初始化成本會壓過優勢。
1 | def counting_sort(a, K): |
Radix Sort
LSD radix 從最低位開始,每一位做穩定 counting sort。例:十進位 170, 45, 75 依個位、十位、百位依序處理。
1 | def radix_sort(a, base=10): |
Bucket Sort
把資料映射到桶,再分別排序後串接。常見分析假設輸入在某區間近似均勻分布;若全擠在同桶,內部排序可能退化。
1 | def bucket_sort(a): |
Linear Search
從頭掃描直到找到 target。它不需要資料有序;若 target 在第一格,最佳是常數時間。
1 | def linear_search(a, target): |
Binary Search
每次把有序搜尋區間砍半。考試常把它泛化成「對單調 predicate 搜尋第一個 True」。
1 | def binary_search(a, target): |
BFS
Queue 保證依距離層數擴張,因此在無權圖中第一次抵達某點即得到最少邊數距離。
1 | from collections import deque |
DFS
沿一路徑深入到底再回溯。遞迴版的 call stack 最壞可到 (O(V)),深圖在 Python 可能需要改 iterative stack。
1 | def dfs(adj, s): |
Dijkstra
每次從 priority queue 取出目前距離最小的頂點並 relax 邊。負邊會破壞 greedy 正確性前提。
1 | import heapq |
Bellman-Ford
重複對所有邊 relax;若一整輪沒有更新可提早停止。做 (V-1) 輪後若仍可 relax,表示存在從 source 可達的負權 cycle。
1 | def bellman_ford(n, edges, s): |
Floyd-Warshall
dist[i][j] 表示目前允許某集合中介點時的最短距離;逐一把 k 加入可用中介點集合。
1 | def floyd_warshall(dist): |
A*
用 (f=g+h) 排 priority。以下為有限圖的簡化 graph-search 版;h(v) 應依問題設計,且若要標準最適性保證需遵守 admissibility/consistency 的相應條件。
1 | import heapq |
Kruskal
把邊依 weight 排序,只接受連接不同 component 的邊。Cycle test 由 DSU 幾乎常數攤銷時間完成。
1 | def kruskal(n, edges): |
Prim
從一個已在 MST 的集合向外擴張最便宜 edge。下面用 heap,適合 adjacency list 的 sparse graph。
1 | import heapq |
Topological Sort
Kahn 演算法把 indegree 0 的頂點放入 queue;若最後輸出頂點數少於 (V),圖中存在 directed cycle。
1 | from collections import deque |
Strongly Connected Components
Kosaraju 先在原圖依 finish time 排序,再在 transpose graph 反向走。兩次 DFS 都是線性,因此總時間仍為 (O(V+E))。
1 | def kosaraju(adj): |
Edmonds-Karp
Ford-Fulkerson 的 augmenting path 固定用 BFS 找最少 edge 數的路徑,因此得到與 capacity 數值無關的 (O(VE^2)) worst-case bound。
1 | from collections import deque |
Dinic
每個 phase 先 BFS 建 level graph,再 DFS 送 blocking flow。下面是精簡 adjacency-list 實作。
1 | from collections import deque |
0/1 Knapsack
一維壓縮時容量 w 必須由大到小更新,否則同一物品會在同一輪被重複使用,變成 unbounded knapsack。
1 | def knapsack_01(weights, values, W): |
Longest Common Subsequence
標準 recurrence:相同字元取左上角 + 1,否則取上方與左方最大值。
1 | def lcs_len(a, b): |
Matrix Chain Multiplication
若矩陣 (A_i) 尺寸為 p[i-1] × p[i],枚舉 interval 長度與切點 k。
1 | def matrix_chain(p): |
Longest Increasing Subsequence
tails[k] 維護目前所有長度 k+1 increasing subsequence 中最小的尾值;它本身不一定是一條實際 LIS,但長度正確。
1 | from bisect import bisect_left |
KMP
先算 pattern 的 prefix function;失配時沿 failure link 跳,不必把 text index 倒退。
1 | def kmp(text, pat): |
Rabin-Karp
維持長度 (m) 視窗的 rolling hash;hash 相等時仍應驗證字串,才能完全避免 collision 造成錯誤答案。
1 | def rabin_karp(text, pat, base=256, mod=1_000_000_007): |
Z-algorithm
維護目前最右的 Z-box [l, r),能把已知 prefix-match 資訊複用,避免從頭重比。
1 | def z_function(s): |
Trie
每個節點代表一個 prefix。以下用 dict children,空間與實際出現的 edge 數較接近,而不是預先配置整個 alphabet。
1 | class Trie: |
Aho-Corasick
多個 pattern 先建 Trie,再用 BFS 建 failure links。以下精簡版回傳每個位置累積到的 pattern 編號。
1 | from collections import deque |
Manacher
利用已知最右回文區間的鏡像資訊,把所有中心的回文半徑在總線性時間內求出。這裡示範 odd-length palindrome 半徑。
1 | def manacher_odd(s): |
Suffix Array
Doubling 法每輪用前 (2^k) 長度的 rank pair 排序,直到所有 suffix rank 唯一。下面 Python 版使用內建 sort,因此概念清楚但常數不是競賽最佳。
1 | def suffix_array(s): |
Suffix Tree
真正的 Ukkonen 線性建構實作較長,不適合「簡短程式碼」附錄。以下教學版是 suffix trie,而非壓縮 suffix tree,也不是 (O(n)) 建構;它只用來展示「把所有 suffix 路徑索引起來後,substring query 沿 edge 走」的核心概念。表格中的 (O(n)) 建構界指 Ukkonen 類 suffix tree。
1 | def build_suffix_trie_for_demo(s): |
Hash Table
下面用 separate chaining 示意 collision。好的 hash 與合理 load factor 下,bucket 期望短,因此主要 operations expected (O(1));若全部 key 落同一 bucket 就可能 (O(n))。
1 | class HashTable: |
Union-Find / DSU
find 做 path compression;union 讓小樹掛到大樹。兩個最佳化同時使用才得到經典的 inverse-Ackermann 攤銷界。
1 | class DSU: |
Segment Tree
每個節點儲存一段區間 aggregate;query 只拜訪 (O(\log n)) 層中少量節點。以下是 iterative range-sum tree,query 區間為 [l, r)。
1 | class SegmentTree: |
Fenwick Tree
利用 i += i & -i 與 i -= i & -i 在隱式樹上跳躍。適合可由 prefix 組合出的操作,range sum 可用兩個 prefix 相減。
1 | class Fenwick: |
Bloom Filter
下例用固定大小 bit array 與多個 salted hash 示意。實務應使用可重現且品質穩定的 hash,而不是把 Python 內建 hash 當跨程序序列化格式。
1 | class BloomFilter: |
Binary Heap
Python heapq 是 min-heap。heapify 能 bottom-up 線性建 heap;push/pop 為 logarithmic。
1 | import heapq |
Sparse Table
對 static RMQ,先預算長度 (2^k) 的區間最小值;因 min 是 idempotent,可用兩個可能重疊的 block 在 (O(1)) 回答 query。
1 | class SparseTableMin: |
參考來源
教科書與大學課程
- CLRS Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein, Introduction to Algorithms, 4th ed., MIT Press。官方頁面:https://mitpress.mit.edu/9780262046305/introduction-to-algorithms/
- MIT-Algorithms MIT OpenCourseWare, 6.006 Introduction to Algorithms,涵蓋 insertion/merge sort、heaps、counting/radix、hashing、graphs 等:https://ocw.mit.edu/courses/6-006-introduction-to-algorithms-fall-2011/
- Princeton Algorithms, 4th ed. companion site:https://algs4.cs.princeton.edu/
原始論文/經典文獻
- AStar-Original Hart, Nilsson, Raphael (1968), A Formal Basis for the Heuristic Determination of Minimum Cost Paths:https://ai.stanford.edu/~nilsson/OnlinePubs-Nils/PublishedPapers/astar.pdf
- KMP-Original Knuth, Morris, Pratt, Fast Pattern Matching in Strings:https://epubs.siam.org/doi/10.1137/0206024
- RK-Original Karp, Rabin, Efficient randomized pattern-matching algorithms:https://ieeexplore.ieee.org/document/5390135/
- Bloom-Original Burton H. Bloom (1970), Space/Time Trade-offs in Hash Coding with Allowable Errors:https://dl.acm.org/doi/10.1145/362686.362692
- Manber & Myers, Suffix Arrays: A New Method for On-Line String Searches:https://epubs.siam.org/doi/10.1137/0222058
- Ukkonen Esko Ukkonen, On-line construction of suffix trees(Springer):https://link.springer.com/article/10.1007/BF01206331
權威教學與演算法參考
- GFG-Sort GeeksforGeeks, Introduction to Sorting Techniques:https://www.geeksforgeeks.org/dsa/introduction-to-sorting-algorithm/
- GFG-Sort-Analysis GeeksforGeeks, Analysis of Different Sorting Techniques:https://www.geeksforgeeks.org/dsa/analysis-of-different-sorting-techniques/
- GFG-Radix GeeksforGeeks, Radix Sort:https://www.geeksforgeeks.org/dsa/radix-sort/
- Princeton-Quick Princeton Algorithms, Quicksort:https://algs4.cs.princeton.edu/23quicksort/
- Princeton-Heap Princeton Algorithms, Priority Queues / Heapsort:https://algs4.cs.princeton.edu/24pq/
- GFG-Linear GeeksforGeeks, Linear Search:https://www.geeksforgeeks.org/dsa/linear-search/
- GFG-Binary GeeksforGeeks, Complexity Analysis of Binary Search:https://www.geeksforgeeks.org/dsa/complexity-analysis-of-binary-search/
- CP-Binary CP-Algorithms, Binary Search:https://cp-algorithms.com/num_methods/binary_search.html
- CP-BFS CP-Algorithms, Breadth First Search:https://cp-algorithms.com/graph/breadth-first-search.html
- GFG-BFS-Space GeeksforGeeks, BFS complexity discussion:https://www.geeksforgeeks.org/dsa/time-and-space-complexity-of-breadth-first-search-bfs/
- CP-DFS CP-Algorithms, Depth First Search:https://cp-algorithms.com/graph/depth-first-search.html
- CP-Dijkstra CP-Algorithms, Dijkstra on Sparse Graphs:https://cp-algorithms.com/graph/dijkstra_sparse.html
- CP-Bellman CP-Algorithms, Bellman-Ford:https://cp-algorithms.com/graph/bellman_ford.html
- GFG-Bellman GeeksforGeeks, Time and Space Complexity of Bellman-Ford:https://www.geeksforgeeks.org/dsa/time-and-space-complexity-of-bellman-ford-algorithm/
- CP-Floyd CP-Algorithms, Floyd-Warshall:https://cp-algorithms.com/graph/all-pair-shortest-path-floyd-warshall.html
- GFG-Shortest GeeksforGeeks, Shortest Path Algorithms: A Complete Guide:https://www.geeksforgeeks.org/dsa/shortest-path-algorithms-a-complete-guide/
- AStar-Complexity A* complexity overview:https://en.wikipedia.org/wiki/A*_search_algorithm
- CP-Kruskal CP-Algorithms, Kruskal with DSU:https://cp-algorithms.com/graph/mst_kruskal_with_dsu.html
- CP-Prim CP-Algorithms, Prim’s Algorithm:https://cp-algorithms.com/graph/mst_prim.html
- GFG-Topo GeeksforGeeks, topological sorting complexity:https://www.geeksforgeeks.org/dsa/topological-sorting/
- CP-SCC CP-Algorithms, Strongly Connected Components:https://cp-algorithms.com/graph/strongly-connected-components.html
- CP-EdmondsKarp CP-Algorithms, Edmonds-Karp:https://cp-algorithms.com/graph/edmonds_karp.html
- CP-Dinic CP-Algorithms, Dinic’s Algorithm:https://cp-algorithms.com/graph/dinic.html
- CP-Knapsack CP-Algorithms, Knapsack Problem:https://cp-algorithms.com/dynamic_programming/knapsack.html
- GFG-LCS GeeksforGeeks, Longest Common Subsequence:https://www.geeksforgeeks.org/dsa/longest-common-subsequence-dp-4/
- GFG-MCM GeeksforGeeks, Matrix Chain Multiplication:https://www.geeksforgeeks.org/dsa/matrix-chain-multiplication-dp-8/
- CP-LIS CP-Algorithms, Longest Increasing Subsequence:https://cp-algorithms.com/dynamic_programming/longest_increasing_subsequence.html
- CP-KMP CP-Algorithms, Prefix Function / KMP:https://cp-algorithms.com/string/prefix-function.html
- CP-RK CP-Algorithms, Rabin-Karp:https://cp-algorithms.com/string/rabin-karp.html
- CP-Z CP-Algorithms, Z-function:https://cp-algorithms.com/string/z-function.html
- Princeton-Trie Princeton Algorithms, Tries:https://algs4.cs.princeton.edu/52trie/
- CP-AC CP-Algorithms, Aho-Corasick:https://cp-algorithms.com/string/aho_corasick.html
- CP-Manacher CP-Algorithms, Manacher’s Algorithm:https://cp-algorithms.com/string/manacher.html
- CP-SA CP-Algorithms, Suffix Array:https://cp-algorithms.com/string/suffix-array.html
- CP-ST CP-Algorithms, Suffix Tree — Ukkonen:https://cp-algorithms.com/string/suffix-tree-ukkonen.html
- GFG-Hash GeeksforGeeks, Introduction to Hashing:https://www.geeksforgeeks.org/dsa/introduction-to-hashing-2/
- CP-DSU CP-Algorithms, Disjoint Set Union:https://cp-algorithms.com/data_structures/disjoint_set_union.html
- CP-Segment CP-Algorithms, Segment Tree:https://cp-algorithms.com/data_structures/segment_tree.html
- CP-Fenwick CP-Algorithms, Fenwick Tree:https://cp-algorithms.com/data_structures/fenwick.html
- GFG-Bloom GeeksforGeeks, Bloom Filter implementation/complexity:https://www.geeksforgeeks.org/java/implementing-bloom-filter-using-murmur-hash-algorithm-in-java/
- CP-Sparse CP-Algorithms, Sparse Table:https://cp-algorithms.com/data_structures/sparse-table.html
中文教學資源
- NTU-Training 國立臺灣大學資訊系統訓練班,演算法課程介紹;課綱列出排序、搜尋、分治、DP、BFS、DFS、MST、網路流、最短路徑,並以 Introduction to Algorithms 為參考書:https://train.csie.ntu.edu.tw/school/courses/course.php?id=3255
- 4yu Blog DSA 系列:整理複雜度、排序、搜尋、圖論、DP、字串等台灣競程/資工常見主題:https://shiyu0318.github.io/
- 台灣資工所準備經驗文章(作為「考試範圍感」而非複雜度權威來源):https://npes87184.github.io/2015-08-04-csie/
一頁式記憶口訣
- 排序:
Bubble/Insertion最佳 (n);Selection永遠 (n^2);Merge/Heap保證 (n\log n);Quick平均 (n\log n)、最壞 (n^2);Counting(n+K);Radix(D(n+B))。 - 圖:
BFS/DFS(V+E);Dijkstra(E\log V) 級且不能有負邊;Bellman-Ford(VE);Floyd(V^3);Kruskal(E\log E);Primsparse (E\log V)、dense (V^2)。 - DP:
Knapsack(nW);LCS(mn);MCM(n^3);LIS(n\log n)。 - 字串:
KMP/Z/Manacher線性;Rabin-Karpexpected 線性、collision 可退化;Suffix Array常見 (n\log n) build;Suffix Tree理論線性 build(有 alphabet/model 前提)。 - 資料結構:
Hashexpected (1);DSUamortized (\alpha(n));Segment/Fenwick(\log n);Sparse Tablebuild (n\log n)、static RMQ query (1);Heappeek (1)、push/pop (\log n)。
<!-- Reference-style hyperlinks used in the complexity tables -->