Appearance
Hash Table
一句话理解
Hash Table 的底层通常仍然依赖数组 / bucket 结构,只是先通过 hash(key) 把任意 key 映射为 bucket,再配合冲突处理完成查找。
所以可以把它记成:
Hash Table = 数组 / Bucket + Hash 映射 + 冲突处理
核心目标:将任意 key 快速映射到有限的存储位置。
基本流程
text
key
↓
hash(key)
↓
bucket index
↓
bucket
↓
value理想情况下无需遍历整个集合,因此:
- 查询:平均 O(1)
- 插入:平均 O(1)
- 删除:平均 O(1)
为什么不是永远 O(1)
不同 key 可能映射到同一个 bucket。
例如:
text
hash(A) % capacity = 3
hash(B) % capacity = 3这称为:
Hash Collision
发生碰撞后仍需进一步比较或寻找存储位置,因此 Hash Table 通常只能描述为平均 O(1)。
极端碰撞情况下可能退化。
Collision Handling
Separate Chaining
同一个 bucket 中组织多个元素:
text
bucket 3
↓
[A] -> [B] -> [C]Open Addressing
如果目标位置已占用,则继续寻找其他位置。
Linear Probing
text
3 occupied
↓
4
↓
5Quadratic Probing
使用非线性的探测间隔寻找空槽。
Load Factor 与 Resize
随着元素数量增加,如果 bucket 数量不变,碰撞通常会越来越频繁。
常用指标是 Load Factor:
当负载过高时,Hash Table 通常会扩容,并将已有元素重新映射到新的 bucket 空间,这个过程通常称为 Resize / Rehash。
核心链路:
text
元素增多
→ Load Factor 上升
→ Collision 风险上升
→ Resize / Rehash
→ 使用更多空间维持较低的平均查询成本Resize 本身可能很贵,但不会在每次普通查询或插入时发生,因此 Hash Table 的常规操作仍通常以平均 / 摊销复杂度讨论。
秋招层面理解到这里即可,不需要为了这一知识点深入具体语言的 Hash Table 源码实现。
Direct Address Table vs Hash Table
如果 key 是小范围、稠密整数:
text
0 ~ 999可以直接:
python
checked = [False] * 1000查询:
python
checked[user_id]为 O(1)。
这称为:
Direct Addressing
为什么仍然需要 Hash Table
如果 key:
text
3
81729372
2000000000直接按 key 建数组会产生巨大的空间浪费。
Hash 可以将巨大、稀疏 key 空间压缩到有限 bucket 空间。
同时 key 还可能是:
- string
- tuple
- user_id
- URL
- filename
- object
Hash Function 可以将这些 key 转换成数组可使用的 bucket。
Trade-off
Hash Table 本质上是在做:
Space-Time Trade-off
使用额外存储空间,换取平均 O(1) 查询。
数据结构选择
text
判断元素是否存在
│
├── 数据量很小
│ └── List
│
├── 小范围稠密整数 Key
│ └── Direct Address Array / Bitmap
│
├── 巨大稀疏 / 复杂 Key 空间
│ └── Hash Table
│
└── 需要有序 / 范围查询
└── TreePython list vs set
频繁判断:
python
x in collectionList
查询:
空间:
Set
平均查询:
空间:
但 Hash Table 通常存在更大的常数空间开销。
Two Sum Pattern
Problem:
python
nums = [3, 1, 4, 7]
target = 8核心思想:遍历当前数字 x,计算:
然后查询:
python
complement in seen如果存在,则找到答案;否则记录:
python
seen[x] = index伪代码:
python
seen = {}
for i, x in enumerate(nums):
complement = target - x
if complement in seen:
return [seen[complement], i]
seen[x] = i复杂度:
- 遍历:O(n)
- 每次 Hash 查询:平均 O(1)
- 总时间:平均 O(n)
- 额外空间:O(n)
核心模式:
利用 Hash Table 把原本 O(n) 的重复历史查询变成平均 O(1)。
高频理解点
- 为什么平均查询 O(1):Hash Function 将 key 定位到有限 bucket,避免扫描整个集合;
- 为什么不是永远 O(1):Collision 会增加进一步查找成本;
- 为什么不用数组直接寻址:巨大、稀疏或非整数 key 会造成空间浪费或无法直接作为下标;
- 什么时候反而用数组:小范围、稠密整数 key;
- 为什么需要 Resize:控制过高 Load Factor 和碰撞率。
Practice:
04_Practice/CS_MCQs/Data_Structure_Lesson_1.md
Related:
01_Common_CS/Data_Structure/05_set-map.md
Mistakes:
05_Mistakes/CS.md
Interview QA:
06_Interview/CS_QA/Data_Structure.md