写在前面
这是今天下午做leetcode contest的第三题,一开始看到的时候以为考察的是图的连通性的问题,没能想出解决方法,后来看Discussion,发现大家都用到了Union-Find,正好《算法》也看到Union-Find,于是就去把这章看完了再来做,下面会先介绍Union-Find,然后写解题思路。
Union-Find(并查集)
由Dynamic Connectivity Problem引出。
问题Context:
有N个node(0, ……, N - 1),(p, q) pair指node p和node q连通(connection),这个连通关系是一个等价关系(自反性、对称性、传递性)。互相之间有通路的节点可以认为是在同一个component中(个人觉得这里也可以说在一个集合中)。
算法可以做到:
- 连通(connect / union)两个节点
两个节点原本处在不同的component中,若将两个节点连通,则两个component也合并为一个(做并操作) - 找到node p所在的component(一般是用该component中某个node的id来指代这个component)
- 判断两个node是否连通
- 获得component的个数
API
public void union(int p, int q);
public int find(int p);
public boolean connected(int p, int q);
public int count();
使用的数据结构
最关键的是记录每一个节点情况的数组
int[] id = new int[N];
两种实现方式
这里只简单记录,《算法》书中有详细分析
Fast-Find
id数组记录的直接是每个node所在的component的identifier,union时,将两个node的identifier设为一致
public int find(int p) {
return id[p];
}
public void union(int p, int q) {
i