🗂️ Arrays & Hashing
陣列與雜湊表——把相似的事物放一起,用索引或鍵值在 O(1) 找到它。
62 題 · 1 篇導讀
📖 分類導讀
相似的事物放一起,是讓環境井然有序的關鍵,這也是電腦世界中陣列(Array)此資料結構的設計理念。 因為事物都在同處,我們可藉索引在常數時間(O(1))內找到對應元素(隨機存取)。
如果不是相似的事物,如果不放在一起,我們還有方法能好好整理它們嗎?可以,用鍵(Key)值(Value)架構即可。 我們先定好一個雜湊(Hashing)函數,讓要管理的事物都依循此函數的判斷放到對應區塊中。這樣就能在常數時間(O(1))內找到鍵所對應的值。
Notes:
- 有時反向遍歷陣列,做法會簡單很多
- 程式碼要一開始就簡潔很難,寫完再整理比較容易
- 善用陣列索引的有序性,有時會比雜湊表還好用
Hash Map 與 Hash Set
兩者底層都是雜湊,差別在「存不存值」:
- Hash Set:只記「在不在」。用於去重、標記已造訪 (visited)、查詢存在性。
- Hash Map:記「鍵對應到什麼」。用於計數(頻率表)、建立索引(值 → 位置)、快取中間結果。
看到「frequency / 出現次數」「unique / 去重」「快速查找 / 是否存在」「兩數配對」這類字眼,第一反應就該是雜湊。
複雜度
| 操作 | 平均 | 最壞 |
|---|---|---|
| 插入 / 查找 / 刪除 | O(1) | O(n) |
平均 O(1) 的前提是雜湊函數把元素夠均勻地散開;當大量鍵碰撞(雜湊到同格)時退化成 O(n)。面試通常假設 O(1),但要知道這個前提存在。
常用技法
- 配對查找(空間換時間):邊遍歷邊把已看過的數存進 Map,查補數只要
O(1),把O(n^2)的巢狀迴圈降為O(n)。 - 正規化鍵 (canonical key):把「等價的東西」映到同一個鍵再分組。例如分組 anagram 時,用「排序後的字串」或「26 個字母的計數」當鍵。
- 資訊指紋去重:對長字串/物件取雜湊當「指紋」,比逐字比對快;代價是極小機率的碰撞(生日悖論:鍵越多碰撞機率上升越快),對正確性要求高時需再驗證。
IMPORTANT
雜湊表不支援範圍查詢(找出「介於 a 與 b 之間的所有鍵」)。需要範圍、前驅後繼、第 k 小時,得改用有序結構(排序陣列 + 二分、平衡樹)。這正是「陣列索引有序性有時勝過雜湊表」的深層原因。
本章深入
- 前綴和 (Prefix Sums):用預處理把「子陣列和」查詢降到
O(1),並搭配 Hash Map 求「和為 k 的子陣列」。