本专栏单纯记录自己刷题过程,便于后续重复刷题更新迭代自己对于同一道题的认知和方法。有好的刷题方法和思路,可以评论区交流,感谢~
具体讲解详见labuladong的算法小抄一书5.11章节。后续会迭代更新自己的分析和理解。
class UnionFind
{
// 记录连通分量
private int count;
// 节点x的父节点是parent[x]
private int[] parent;
// 记录每棵树的“重量”
private int[] size;
// 构造函数,n为图的节点总数
public UnionFind(int 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;
}
}
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--;
}
public boolean connected(int p, int q)
{
int rootP = find(p);
int rootQ = find(p);
return rootP == rootQ;
}
// 返回某个节点x的根节点
private int find(int x)
{
// 根节点的parent[x] == x
while (parent[x] != x)
{
// 进行路径压缩
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
public int count()
{
return count;
}
}