什么是并查集
并查集可以解决什么问题:判断两个节点是否在一个集合,也可以将两个节点添加到一个集合中。
并查集常用于处理大规模数据下的元素分组问题,特别是在数据量极大时,使用正常的数据结构可能会导致空间或时间复杂度过高。并查集通过其高效的数据处理能力,能够在有限的时间内完成元素的合并和查询操作,特别适用于竞赛编程和实际工程应用中。
leetcode题目: 冗余连接 冗余连接 II 省份数量 最长连续序列 统计无向图中无法互相达到的点数
并查集(Union-find Sets)是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题
-些常见的用途有求连通子图、求最小生成树的Kruskal 算法和求最近公共祖先(LCA)等。
基本原理:每个集合用一个树来表示,树的 root 的代表整个集合,每个节点存储它的父节点,parent[x] 表示 x 的父节点。
并查集通常包含两种操作:
- 初始化
每个节点的父节点指向自己
- 查询 find
如果两个节点是连通的,那么他们一定拥有相同的根节点
通用模版
public class Solution {
//记录连通分量个数
private int count;
//节点x的根节点是parent[x]
private int[] parent;
// 记录树的“重量”
private int[] size;
public Solution(int n){
//一开始互不相通 连通分量等于n
this.count = n;
//一开始,每个节点是自己的父节点
parent = new int[n];
size = new int[n];
for (int i = 0; i < n ; i++) {
parent[i] = i;
size[i] = 1;
}
}
/**
* 将p和q连接, 如果两个节点被连通,那么则让其中的一个根节点连接到另一个节点的根节点上
*/
public void union(int p,int q){
int rootP = find(p);
int rootQ = find(q);
if(rootP == rootQ){
return;
}
//将两颗树合并为一颗,小树接到大树下面,较平衡
if (size[rootP] > size[rootQ]) {
parent[rootQ] = rootP;
size[rootP] += size[rootQ];
} else {
parent[rootP] = rootQ;
size[rootQ] += size[rootP];
}
//两个分量合二为一
count--;
}
/**
* 返回某个节点x的根节点
*/
private int find(int x){
//根节点的parent[x] == x
while (parent[x] != x){
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
/**
* 判断p和q是否连通:如果两个节点是连通的,那么他们一定拥有相同的根节点
*/
public boolean connected(int p,int q){
int rootP = find(p);
int rootQ = find(q);
return rootP == rootQ;
}
/**
* 返回具体有多少个连通分量
*/
public int count(){
return count;
}
}