跳转至

LeetCode 複雜度總表(完整速背版)

更新日期:2026-03-29(已用官方/權威來源交叉查證)
目標:給你一份「先快背、再細看」的完整 Big-O 速查表。


0) 符號約定(先看這個)

符號 意義
n 陣列/字串/節點數量(一般資料量)
m 邊數(Graph edges)
V, E 圖的點數、邊數
k 額外參數(例如 top-k、字母表大小、桶數)
L 字串長度(或單字長度)
W 背包容量(weight/capacity)
α(n) 反 Ackermann 函數(極慢成長,實務可視為接近常數)

0.1 你剛問的重點:什麼是 amortized?

一句話
amortized O(1) 不是「每一次都 O(1)」,而是「做很多次後,平均每次成本是 O(1)」。

用 C++ vector::push_back 直覺理解

  • 平常尾插:直接放進去,成本 O(1)
  • 容量滿了:配置更大記憶體 + 搬移舊元素,這次可能 O(n)
  • 但擴容不會每次發生,只會偶爾發生
  • 所以連續做很多次 push_back,總成本是線性,平均下來每次是 O(1)(攤銷)

小例子(概念):

  • 連續做 8 次 push_back,可能只有第 1、2、4、8 次附近有擴容成本
  • 總成本雖然有幾次很貴,但分攤到 8 次操作後,平均仍是常數級

[!TIP] 面試說法可以用這句:
push_back is O(1) amortized, with occasional O(n) reallocation.”


0.2 static array vs dynamic array(C++ 版)

A) Static Array(靜態陣列)

  • 大小固定,建立後不可改
  • 記憶體通常在 stack(區域變數)或靜態區(全域/static
  • 存取 arr[i]O(1)
  • 不需要擴容邏輯,常數因子小
int a[100];               // compile-time fixed size
std::array<int, 100> b;   // fixed-size wrapper

B) Dynamic Array(動態陣列)

  • 大小可變(可 grow/shrink)
  • 記憶體在 heap,容器要管理 sizecapacity
  • 隨機存取仍是 O(1)
  • 尾插通常 O(1) amortized,擴容那次最壞 O(n)
std::vector<int> v;
v.push_back(42);          // amortized O(1)

C) 快速對照

比較項目 Static Array Dynamic Array (vector)
大小是否可變
記憶體位置 stack/靜態區(常見) heap(由 allocator 管理)
random access O(1) O(1)
尾端新增 不適用(固定大小) O(1) amortized,偶爾 O(n)
中間插入/刪除 O(n) O(n)
使用情境 已知固定大小、追求簡單高效 大小不確定、需要彈性

1) 30 秒速背總表(面試前最後看)

類別 操作/演算法 Average Worst 備註
Dynamic Array random access O(1) O(1) arr[i]
Dynamic Array append (尾插) O(1) amortized O(n) 擴容時搬移
Dynamic Array insert/delete middle O(n) O(n) 需位移
Hash Table search/insert/delete O(1) O(n) 碰撞極端情況
Balanced BST (map/set) search/insert/delete O(log n) O(log n) 紅黑樹等
Heap push / pop O(log n) O(log n) top=O(1)
BFS / DFS 圖遍歷 O(V+E) O(V+E) adjacency list
Binary Search 查找 O(log n) O(log n) 已排序前提
Merge Sort 排序 O(n log n) O(n log n) 穩定,額外 O(n)
Quick Sort 排序 O(n log n) O(n^2) pivot 選不好會退化
Dijkstra (heap) 最短路 O((V+E)logV) O((V+E)logV) 邊權非負
Bellman-Ford 最短路 O(VE) O(VE) 可處理負權
Floyd-Warshall 全點對最短路 O(V^3) O(V^3) 小圖常用
DSU (Union-Find) find/union O(α(n)) amortized 單次可到 O(log n) 路徑壓縮+按秩合併

2) 資料結構操作複雜度(通用)

2.1 線性結構

資料結構 操作 Average Worst 備註
Array (static) access by index O(1) O(1) 連續記憶體
Array (static) search O(n) O(n) 未排序
Array (static) insert/delete O(n) O(n) 需搬移
Dynamic Array access by index O(1) O(1) vector/list
Dynamic Array append O(1) amortized O(n) reallocation
Dynamic Array pop back O(1) O(1)
Dynamic Array insert/delete at i O(n) O(n) 位移
Singly Linked List access by index O(n) O(n) 無隨機存取
Singly Linked List search O(n) O(n)
Singly Linked List insert/delete head O(1) O(1)
Singly Linked List insert after known node O(1) O(1) 已拿到節點指標
Doubly Linked List insert/delete head/tail O(1) O(1)
Doubly Linked List delete known node O(1) O(1)
Stack push/pop/top O(1) O(1)
Queue enqueue/dequeue/front O(1) O(1)
Deque push/pop both ends O(1) O(1)

2.2 雜湊、樹、優先佇列

資料結構 操作 Average Worst 備註
Hash Table search/insert/delete O(1) O(n) hash collision 退化
Binary Search Tree (未平衡) search/insert/delete O(log n) O(n) skew tree 退化
Balanced BST (AVL/RB) search/insert/delete O(log n) O(log n)
Heap (binary) top O(1) O(1)
Heap (binary) push / pop O(log n) O(log n)
Heap (binary) build heap O(n) O(n)
Trie insert/search/delete O(L) O(L) L 為 key 長度
Union-Find (DSU) find/union O(α(n)) amortized 單次可到 O(log n) 路徑壓縮 + union by rank/size

2.3 區間資料結構(LeetCode 高頻)

結構 建構 查詢 更新 空間
Prefix Sum O(n) O(1) 區間和 單點改值 O(n) O(n)
Difference Array O(n) 回復原陣列 O(n) 區間加值 O(1) O(n)
Fenwick Tree (BIT) O(n) prefix/range O(log n) O(log n) O(n)
Segment Tree O(n) O(log n) O(log n) O(n)(常見實作約 4n
Sparse Table O(n log n) O(1)(idempotent,如 min/max/gcd) 不支援動態更新 O(n log n)

3) 語言容器速查(LeetCode 常用)

3.1 Python(CPython)

容器 操作 Average Worst 備註
list a[i] 讀寫 O(1) O(1) 動態陣列
list append O(1) 單次可 O(n) 攤銷常數
list pop() (尾端) O(1) O(1)
list insert(i,x) / pop(i) O(n) O(n) 位移
list x in list O(n) O(n) 線性掃描
collections.deque append/appendleft O(1) O(1) 雙端高效
collections.deque pop/popleft O(1) O(1)
collections.deque remove(x) O(n) O(n)
dict get/set/del/in O(1) O(n) hash table
set add/remove/in O(1) O(n) hash table
set union s|t O(len(s)+len(t)) O(len(s)+len(t))
set intersection s&t O(min(len(s),len(t))) O(len(s)*len(t))

註:Python 官方 wiki 明確區分 average 與 worst;worst-case 多半來自碰撞或極端配置。

3.2 C++ STL(常見容器)

容器 操作 Average Worst 備註
vector random access O(1) O(1)
vector push_back O(1) amortized O(n) 擴容搬移
vector insert/erase middle O(n) O(n)
deque random access O(1) O(1)
deque push/pop front/back O(1) O(1)
deque insert/erase middle O(n) O(n)
list insert/erase known iterator O(1) O(1) 雙向 linked list
list random access / search O(n) O(n)
map / set search/insert/erase O(log n) O(log n) 紅黑樹
unordered_map / unordered_set search/insert/erase O(1) O(n) 平均常數、最壞線性
priority_queue top O(1) O(1) heap top
priority_queue push/pop O(log n) O(log n)

4) 排序 / 選擇 / 搜尋演算法

4.1 排序總表

演算法 Best Average Worst Extra Space Stable 備註
Bubble Sort(優化版) O(n) O(n^2) O(n^2) O(1) 幾乎不用於實戰
Selection Sort O(n^2) O(n^2) O(n^2) O(1) 交換次數少
Insertion Sort O(n) O(n^2) O(n^2) O(1) 小資料很實用
Merge Sort O(n log n) O(n log n) O(n log n) O(n) 穩定
Quick Sort O(n log n) O(n log n) O(n^2) O(log n) avg recursion pivot 決定退化風險
Heap Sort O(n log n) O(n log n) O(n log n) O(1) 原地但不穩定
Counting Sort O(n+k) O(n+k) O(n+k) O(n+k) 可穩定 k 為值域
Radix Sort O(d(n+k)) O(d(n+k)) O(d(n+k)) O(n+k) 視底層排序 d 位數
Bucket Sort O(n+k) O(n+k)(分布佳) O(n^2) O(n+k) 視實作 依資料分布
Timsort(Python sort) O(n) O(n log n) O(n log n) O(n) 真實工程常用

4.2 搜尋 / 選擇

演算法 Average Worst 備註
Linear Search O(n) O(n)
Binary Search(已排序) O(log n) O(log n)
Quickselect(第 k 小/大) O(n) O(n^2) 隨機 pivot 可改善期望

5) 圖論演算法(LeetCode 高頻)

演算法 時間複雜度 空間複雜度 備註
BFS O(V+E) O(V) adjacency list
DFS O(V+E) O(V) 遞迴棧最深可到 V
Topological Sort(Kahn/DFS) O(V+E) O(V) DAG
Dijkstra(binary heap) O((V+E)logV) O(V+E) 邊權需非負
Dijkstra(dense/array) O(V^2) O(V^2)O(V+E) 稠密圖常見
Bellman-Ford O(VE) O(V) 可處理負權、可檢測負環
Floyd-Warshall O(V^3) O(V^2) 全點對最短路
Kruskal (MST) O(E log E)(≈O(E log V) O(V) 排序邊 + DSU
Prim(binary heap) O(E log V) O(V+E)
Prim(adj matrix) O(V^2) O(V^2)
SCC(Tarjan/Kosaraju) O(V+E) O(V)
Bridge / Articulation Point O(V+E) O(V) low-link
Union-Find per op O(α(n)) amortized O(n) 連通分量題常用

6) DP / 回溯 / 字串 / 數學

6.1 動態規劃(經典)

問題/方法 時間 空間 備註
Fibonacci / Climbing Stairs O(n) O(1) 可優化
0/1 Knapsack O(nW) O(W)(壓縮後) pseudo-polynomial
Coin Change O(n*amount) O(amount)
LIS(binary search 解) O(n log n) O(n)
LIS(DP 解) O(n^2) O(n)
LCS O(nm) O(nm)
Edit Distance O(nm) O(nm) 可優化到 O(min(n,m))
Interval DP(常見) O(n^3) O(n^2) 例:區間合併類

6.2 回溯 / 搜尋樹

類型 時間(常見上界) 空間 備註
Subsets O(2^n) O(n)(遞迴深度) 輸出本身也是 2^n
Permutations O(n!) O(n)
Combination(n 選 k) O(C(n,k) * k) O(k)
N-Queens O(n!) O(n) 強烈依剪枝

6.3 字串演算法

演算法 時間 空間 備註
KMP O(n+m) O(m) n 文本、m pattern
Z-Algorithm O(n) O(n)
Rabin-Karp 平均 O(n+m) 最壞 O(nm) hash collision 退化
Trie Search/Insert O(L) O(total chars)

6.4 數學與位元

方法 時間 空間 備註
Fast Power(Binary Exponentiation) O(log n) O(1)O(log n) 遞迴
Euclid GCD O(log min(a,b)) O(1)
Sieve of Eratosthenes O(n log log n) O(n)
位元計數(固定 32/64 位) O(1) O(1) 若以 machine word 視角

7) LeetCode 高頻模板複雜度(超實用)

模板 時間 空間 關鍵備註
Two Pointers(同向/對撞) O(n) O(1)
Sliding Window O(n) O(1)~O(k) 每元素進出窗口最多一次
Monotonic Stack O(n) amortized O(n) 每元素 push/pop 最多一次
Monotonic Deque O(n) amortized O(n) Sliding Window Maximum 經典
Prefix Sum build O(n), query O(1) O(n)
Binary Search on Answer O(logR * check(n)) 依 check R 為答案範圍
Meet in the Middle O(2^(n/2)) O(2^(n/2)) 指數降半常用於 n<=40

8) 最容易背錯的 10 件事(務必記住)

  1. unordered_map / dict平均 O(1),不是保證最壞 O(1)
  2. Dynamic Array 的 append攤銷 O(1),單次可能 O(n)
  3. list.pop(0) 在 Python 是 O(n),不是 O(1)
  4. Quick Sort 不是永遠 O(n log n);最壞 O(n^2)
  5. BFS/DFS 的 O(V+E) 是在 adjacency list;若用 matrix 會變 O(V^2)
  6. Dijkstra 不能處理負權邊。
  7. DSU 的 O(α(n))amortized,不是每次嚴格常數。
  8. Heap 的 topO(1),但 push/popO(log n)
  9. BST 若不平衡會退化到 O(n)
  10. DP 的時間常常取決於狀態數 × 轉移數,先數這兩個再下結論。

9) 查證來源(本次整理實際檢查)

官方/權威容器複雜度

演算法複雜度(cp-algorithms)

補充(排序總覽)


10) 使用建議(背誦路線)

  1. 先背「30 秒速背總表」。
  2. 再背「第 7 節高頻模板」。
  3. 最後補齊「第 4、5、6 節」細節(尤其圖論與 DP)。
  4. 每次刷題寫下:time = ?space = ?why,背得最快。