并查集面试题总结:路径压缩、连通性与 Java 模板
并查集用接近常数的均摊代价回答”两个元素是否同组、合并后还剩几个集合”,是动态连通性问题与 Kruskal 最小生成树的标配。本文拆解它的森林模型、两种关键优化与建模套路。
它解决什么问题
大量问题只关心”分组”而不关心”路径”:两个用户是否在同一个社交圈、加入一条边之后图里还剩几个连通块、无向图里这条边会不会构成环。每次用 BFS/DFS 现场搜索要 O(V+E),而真实场景里关系不断合并、查询海量,搜索派的成本很快失控。并查集换一种思路:把连通关系预先维护在结构里,查询时只需比对两个元素的”集体身份”。
核心原理
把每个集合组织成一棵树,树根充当整个集合的代表元。parent[x] 记录 x 的父节点,根的父节点是它自己;初始时 n 个元素各自成树,即 n 个集合。find(x) 沿父指针一路爬到根,根就是 x 所在集合的身份;union(a, b) 先各自 find 找根,根相同说明已连通,否则把一棵树挂到另一棵的根下。判断连通等价于 find(a) == find(b);统计连通分量则维护一个计数器,每次真正合并成功才减一。
理解演进路径有助于记住设计动机:Quick Find 让数组直接存集合编号,查询 O(1) 但合并要扫全表;Quick Union 改存父指针,合并只动一个根,却可能养出高树。实用并查集就是在 Quick Union 上叠加两种抑高手段的产物。
深入机制
朴素实现的退化与两种优化
朴素的 Quick Union 任意挂接,极端情况下树退化成一条长链,find 劣化到 O(n)。两种优化从不同方向封堵退化:
- 按秩(或按大小)合并:永远把小树挂到大树下。直觉是树高只在”规模翻倍”时才可能加一,因此深度上界被压到 O(log n)。
- 路径压缩:find 返回途中,顺手把路径上的节点直接挂到根下。这次查询多走的每一步,都在为之后的查询铺路。
class UnionFind { |
近 O(1) 的直觉
两种优化叠加后,m 次操作的均摊成本是 O(m·α(n)),α 为反阿克曼函数。阿克曼函数增长快到超越常规直觉,其反函数则慢到几乎停滞:n 取到可观测宇宙的原子总数,α(n) 也不超过 4。所以工程与面试中都说”近似常数”,但要注意理论上它不是严格 O(1),精确表述是均摊 O(α(n))。空间为 O(n),即 parent 与 size 两个数组。
连通性问题的建模套路
- 编号:把对象映射到 0..n-1,二维网格用
i * cols + j拍平; - 合并:凡是”二者属于同一组”的条件,一律 union;
- 回答:connected 答连通性,count 答分量数,union 返回 false 正好暴露冗余边与环。
工程实践
- 岛屿数量:每块陆地与相邻陆地 union,结束后分量数即岛屿数;陆地动态增加的场景下,并查集比反复重搜自然得多。
- 冗余连接:依次读入边,第一条两端已然连通的边就是答案——它正是成环的那条。
- 等式与账户合并:先把所有”相等、同属”关系 union 完,再逐条检查”不等”约束两端是否被误并,冲突即无解;邮箱账户合并也是同一套先并后查的剧本。
- Kruskal 最小生成树:边按权升序排序,逐条 union,成功则选入,凑满 V-1 条即得 MST。成环判定被压到近 O(1),总复杂度由排序主导,O(E log E)。
int kruskal(int n, int[][] edges) { // edges 元素为 {u, v, w} |
也要认清边界:路径压缩会抹掉”当初靠哪条边连通”的信息,所以并查集不支持删边、给不出两点间的具体路径,也无法表达有向可达。离线删除场景可以把操作序列倒过来,把删除变回添加;要维护”x 与 y 的差值或倍数”这类关系,则需带权并查集。
对比与权衡
| 方案 | 单次连通查询 | 动态加边 | 支持删边 | 给出路径 | 适用场景 |
|---|---|---|---|---|---|
| 并查集(双优化) | 均摊近 O(1) | 均摊近 O(1) | 否 | 否 | 动态连通性、分量统计 |
| BFS / DFS | O(V+E) | 需重搜 | 需重搜 | 是 | 静态图、需要路径 |
| Quick Find | O(1) | O(n) | 否 | 否 | 查询极多且几乎无合并 |
面试视角
union 为什么必须挂根而不是直接挂元素? 集合身份由根代表,只有根对根挂接才能保证两棵树的全体成员身份统一;随手挂中间节点会让部分成员”脱离集体”,连通性判断直接出错。
路径压缩会不会破坏正确性? 不会。压缩只改变节点在树里的挂载位置,不改变它所属的根,连通信息无损,纯粹是为后续查询提速的结构调整。
能说并查集操作是 O(1) 吗? 严格说不能。双优化下均摊 O(α(n)),α 增长极慢、实用中恒为常数级,所以工程上称近似 O(1);面试答出反阿克曼函数才算完整。
并查集能判有向图的环吗? 不能,它只表达无向连通性,”a 与 b 连通”不蕴含”a 可达 b”。有向判环要用拓扑排序或三色标记 DFS。
二维网格题怎么套并查集? 把 (i, j) 映射成一维编号 i * cols + j,四方向相邻的陆地做 union;行或列可能很大时改用 Map 存 parent,只为真实出现的格点建节点。
小结
- 模型一句话:森林加代表元,find 找根、union 挂根、connected 比根。
- 按秩合并压制树高,路径压缩摊薄查询,双优化把均摊成本压到近 O(1)。
- 建模三步走:编号、见关系就 union、用 count / connected / union 返回值回答业务问题。
- 岛屿、冗余连接、Kruskal 是三大经典战场;删边、求路径与有向可达则超出它的能力圈。

