并查集代码实现:
public class UnionFind {
private int count; //记录连通分量,即块数多少
private int[]parent; //节点x的根节点是parent[x]
public UnionFind(int n){
//一开始互不相通
this.count=n;
//一开始,每个节点是自己的父节点
parent=new int[n];
for (int i = 0; i <n ; i++) {
parent[i]=i;
}
}
//将p和q连接, 如果两个节点被连通,那么则让其中的一个根节点连接到另一个节点的根节点上
public void union(int p,int q){
int rootP=find(p);
int rootQ=find(q);
if(rootP==rootQ){//根节点一样。
return;
}
//将两颗树合并为一颗
parent[rootP]=rootQ; //parent[rootQ]=rootP 效果是一样的
count--; //两个分量合二为一
}
//返回某个节点x的根节点
private int find(int x){
//根节点的parent[x]==x
while (parent[x]!=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;
}
}
详解并查集:力扣
class Solution {
public int findCircleNum(int[][] isConnected) {
UnionFind uf=new UnionFind(isConnected.length);
for(int i=0;i<isConnected.length-1;i++){
for(int j=i+1;j<isConnected.length;j++){
if(isConnected[i][j]==1){//两个集合有相连部分。
uf.union(i,j);
}
}
}
return uf.size;//返回集合块数
}
}
class UnionFind{//并查集类
int[] roots;//每个集合的代表,即在该集合的所有元素的根节点。
int size;//集合块数。
public UnionFind(int n){
roots=new int[n];
for(int i=0;i<n;i++){//最开始每个元素都是一块集合,各自为政
roots[i]=i;
}
size=n;
}
public int find(int i){//找集合的代表元素
if(i==roots[i])//这种情况是集合内只有一个元素。
return i;
return roots[i]=find(roots[i]);//继续找,直到找到代表元素。
}
public void union(int p,int q){//两个元素相连看他们是否是在同一个集合中
int proot=find(p);//找代表元素
int qroot=find(q);//找代表元素
if(qroot!=proot){//代表元素不同则说明在不同集合中,但这两个集合有连接部分
roots[qroot]=proot;//将两个集合合并
size--;//集合块数--
}
}
}