class UnionFind {
private parent: number[];
private rank: number[];
constructor(size: number) {
this.parent = Array(size).fill(0).map((_, i) => i);
this.rank = Array(size).fill(0);
}
find(x: number): number {
if (this.parent[x] !== x) {
this.parent[x] = this.find(this.parent[x]); // path compression
}
return this.parent[x];
}
union(x: number, y: number): void {
const rootX = this.find(x);
const rootY = this.find(y);
if (rootX === rootY) return; // already in same group
if (this.rank[rootX] < this.rank[rootY]) {
this.parent[rootX] = rootY; // attach smaller tree under bigger
} else if (this.rank[rootX] > this.rank[rootY]) {
this.parent[rootY] = rootX;
} else {
this.parent[rootY] = rootX;
this.rank[rootX] += 1; // increase rank if same
}
}
connected(x: number, y: number): boolean {
return this.find(x) === this.find(y);
}
}
// Driver code
const uf = new UnionFind(5);
uf.union(0, 1);
uf.union(1, 2);
console.log('0 and 2 connected:', uf.connected(0, 2));
uf.union(3, 4);
console.log('0 and 4 connected:', uf.connected(0, 4));if (this.parent[x] !== x) {
this.parent[x] = this.find(this.parent[x]); // path compression
}
compress path to root to speed up future finds
const rootX = this.find(x);
const rootY = this.find(y);
if (rootX === rootY) return;
find roots and skip union if already connected
if (this.rank[rootX] < this.rank[rootY]) {
this.parent[rootX] = rootY;
} else if (this.rank[rootX] > this.rank[rootY]) {
this.parent[rootY] = rootX;
} else {
this.parent[rootY] = rootX;
this.rank[rootX] += 1;
}
attach smaller tree under bigger to keep tree shallow
return this.find(x) === this.find(y);
check if two elements share the same root
0 and 2 connected: true
0 and 4 connected: false