class UF{
int count;
int[] parent;
int[] size;
public UF(int n){
this.count = n;
parent = 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[Q] = rootP;
size[rootP] +=size[rootQ]
}else(
parent[P] = rootQ;
size[rootQ] += size[rootP];
}
count --;
}
public connect(int p,int q){
return find(p) == find(q);
}
//返回x的根结点
private int find(int x){
while(x != parent[x]){
//路径压缩
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
}
- 用parent数组记录每一个节点的父节点,相当于指向父节点
- size记录每棵树的重量,目的让union后拥有平衡性
- find函数进行路径压缩,使得union和connect时间复杂度为O(1)
很多使用DFS深度有限算法的问题也可以用Union-Find算法解决
装着若干字符串表示的算式的数组equations,每个算式equations[i]长度都是4,只有两种情况
a==b or a!=b,其中a,b可以是任意小写字母
若所有算式都不会互相冲突,返回true,否则返回false
动态连通性是一种等价关系,具有自反性,传递性,对称性
boolean equationsPossible(String[] equations){
//26个英文字母
Uf uf = new Uf(26);
for(String eq: equations){
if(eq.charAt(1) == '='){
char x = eq.charAt(0);
char y = eq.charAt(3);
uf.union(x - 'a',y-'a');
}
}
//检查不等关系是否打破相等关系
for(String eq: equations){
if(eq.charAt(1) == '1'){
char x = eq.charAt(0);
char y = eq.charAt(3);
if(uf.connected(x-'a',y-'a') return false;
}
}
return ture;
}
private void union(int p, int q){
int pRoot = find(p);
int qRoot = find(q);
if(size[pRoot]>size[qRoot]){
parent[qRoot] = pRoot;
size[pRoot] += size[qRoot];
}else{
size[qRoot] += size[pRoot];
parent[pRoot] = qRoot;
}
}
boolean connected(int p, int q){
int rootP = find(p);
int rootQ = find(q);
return rootP == rootQ;
}
int find(int x){
while(parent[x] != x){
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}