C++ 演算法面試常函式
目錄
簡介
這邊介紹我自己在解題會用到的小抄以及解題想法。
解題思路
- 看題目:先想資料範圍、資料儲存形式、正負與大小會不會有影響、加總、乘積會不會超過
INT_MAX等,這個是當下要跟面試官討論的部分- 想題目的 edge case
- Overflow
- 先講暴力破解方法,並且分析時間跟空間複雜度
- 開始想資料結構和演算法優化
- One-pointer
- Greedy
- Prefix sum
- Two-pointer
- 兩邊慢慢集中到中間
- Sliding window
- 快慢指標
- Sort
- Binary search
- Divide and Conquer
- DP
- Retrieve
- Top-down/Bottom-up
- One-pointer
常用資料結構
以下先提供各種小抄:
| 情況 | 適用 |
|---|---|
| 要自動排序 | set / map |
| 不在乎順序、只求快 | unordered_set / unordered_map |
| 允許重複 key | multi* |
| 要 key → value | map |
| 只有 key | set |
| 資料結構 | 取值 (Index) | 搜尋 | 插入 | 刪除 | get min/max |
|---|---|---|---|---|---|
| 陣列 (array) | O(1) |
O(n) |
|||
| 動態陣列 (vector) | O(1) |
O(n) |
O(n) |
O(n) |
O(n) |
| 雙向串列 (list) | O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
| 紅黑樹 (set) | O(log n) |
O(log n) |
O(log n) |
O(log n) |
O(log n) |
| 紅黑樹 (multiset) | O(log n) |
O(log n) |
O(log n) |
O(log n) |
O(log n) |
| Hash table (u_set) | O(1) |
O(1) |
O(1) |
O(1) |
O(n) |
| Hash table (u_multiset) | O(1) |
O(1) |
O(1) |
O(1) |
O(n) |
| 紅黑樹 (map) | O(log n) |
O(log n) |
O(log n) |
O(log n) |
O(log n) |
| 紅黑樹 (multimap) | O(log n) |
O(log n) |
O(log n) |
O(log n) |
O(log n) |
| Hash table (u_map) | O(1) |
O(1) |
O(1) |
O(1) |
O(n) |
| Hash table (u_multimap) | O(1) |
O(1) |
O(1) |
O(1) |
O(n) |
| stack | O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
| queue | O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
| Binary heap (PQ) | O(n) |
O(log n) |
O(log n) |
O(1) |
| 資料結構 | 取值 (Index) | 搜尋 | 插入 | 刪除 | get min/max |
|---|---|---|---|---|---|
| 陣列 (array) | O(1) |
O(n) |
|||
| 動態陣列 (vector) | O(1) |
O(n) |
O(n) |
O(n) |
O(n) |
| 雙向串列 (list) | O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
| 紅黑樹 (set/map) | O(log n) |
O(log n) |
O(log n) |
O(log n) |
O(log n) |
| Hash table (u_*) | O(1) |
O(1) |
O(1) |
O(1) |
O(n) |
| stack / queue | O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
| Binary heap (PQ) | O(n) |
O(log n) |
O(log n) |
O(1) |
| 資料結構類型 | 資料結構 | 核心應用場景與特性 | 經典 LeetCode 例子 / 備註 |
|---|---|---|---|
| 線性容器 | vector | 隨機存取 (Index)、排序後處理、雙指標 (Two Pointers) | 3Sum, Merge Intervals, 前綴和應用 |
| deque | 兩端快速進出、Sliding Window (找區間最值)、0-1 BFS | Sliding Window Maximum (239) | |
| 有序容器 | set | Key 唯一、自動排序、動態維護最小/最大值、區間查詢 | Contains Duplicate II, 去重 + 排序 |
| multiset | 允許重複 Key、自動排序、動態中位數、排行統計 | Find Median from Data Stream (295) | |
| map | 按 Key 排序輸出結果、區間統計 | My Calendar 系列, 頻率排序後輸出 | |
| multimap | 幾乎不用,建議改用 map<K, vector<V>> |
方便對單一 Key 的多個 Value 進行批次處理 | |
| 無序容器 | u_set | 快速存在性檢查、去重、循環檢測 | Two Sum, Happy Number, Detect Cycle |
| u_map | 頻率統計、計數、哈希映射、子陣列和 (Subarray Sum) | Subarray Sum Equals K (560), Anagram | |
| u_multi* | 極少見,通常 u_map 搭配 vector 可涵蓋其功能 |
— | |
| 容器適配器 | stack | 括號匹配、DFS (迭代版)、表達式計算、單調棧 | Valid Parentheses, Daily Temperatures |
| queue | 層序遍歷 (BFS)、緩衝區、生產者消費者模型 | Binary Tree Level Order Traversal | |
| priority_queue | Top K 元素、排程演算法、多路歸併 | Merge k Sorted Lists, Kth Largest Element |
stack, queue, and priority_queue
注意 construct heap 是 O(n),但排序整個 heap 是 nlog(n)
常用演算法函式
-
binary_search,lower_bound,upper_boundint a[100]= {4,10,11,30,69,70,96,100}; int b=binary_search(a,a+9,4);//查找成功,返回1 cout<<"在数组中查找元素4,结果为:"<<b<<endl; int c=binary_search(a,a+9,40);//查找失败,返回0 cout<<"在数组中查找元素40,结果为:"<<c<<endl; int d=lower_bound(a,a+9,10)-a; cout<<"在数组中查找第一个大于等于10的元素位置,结果为:"<<d<<endl; int e=lower_bound(a,a+9,101)-a; cout<<"在数组中查找第一个大于等于101的元素位置,结果为:"<<e<<endl; int f=upper_bound(a,a+9,10)-a; cout<<"在数组中查找第一个大于10的元素位置,结果为:"<<f<<endl; int g=upper_bound(a,a+9,101)-a; cout<<"在数组中查找第一个大于101的元素位置,结果为:"<<g<<endl -
sortstd::sort(arr, arr+10, std::greater<int>()); std::sort(v.begin(), v.end(), [](int a, int b){ return a < b; // 升序排列 }); -
reversereverse(a.begin()+2, a.begin()+6); -
next_permutationnext_permutation(a, a+3); -
accumulate(arr.begin(), arr.end(), 0);
演算法
- Pointer
- Two pointers
- Sliding window
- Prefix sum
- Graph
- BFS/DFS
- Union Find
- Topological Sort
- Search
- Binary Search
其他
Policy-Based Data Structures (PBDS)
GCC 編譯器內建的一套強大擴充庫,雖然它不屬於標準 C++ STL,但因為 Leetcode 是使用 GCC 環境編譯,所以你可以直接調用。
有各種額外的資料結構,像是:
- Order Statistic Tree (能查排名的平衡樹),在標準 STL 中,set 只能幫你排序和去重,但它沒辦法在 $O(\log n)$ 時間內告訴你「某個數字是第幾名」或「第 $k$ 大的數字是誰」,PBDS 補足了這個缺憾
- gp_hash_table: 比 unordered_map 快非常多的 Hash Table(在某些題目可以避免被惡意測資卡掉)
- Priority Queue: 比 STL 的更強大,支持 join(合併兩堆只要 $O(1)$ 或 $O(\log n)$)。