Tracking Connected Components
[!NOTE] This module explores the core principles of Union-Find (Disjoint Set Union), deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.
1. Concept Definition
Problem: Given a set of elements, we want to:
- Union(A, B): Connect element A and element B.
- Find(A): Determine which group (component) A belongs to.
Applications: Kruskal’s MST Algorithm, Cycle Detection in Undirected Graphs, Grid Connectivity (Number of Islands).
Optimization:
- Path Compression: Point nodes directly to the root during
find. - Union by Rank/Size: Attach the smaller tree to the larger tree to keep height low.
- Result: Time complexity becomes O(alpha(N)) (Inverse Ackermann function), which is effectively O(1) for all practical N.
2. Interactive Analysis
Union nodes and watch them merge. Find highlights the path to the representative (Root).
Parents: [0, 1, 2, 3, 4, 5]
3. Implementation
Java
Go
class DSU {
int[] parent;
int[] rank;
public DSU(int n) {
parent = new int[n];
rank = new int[n];
for (int i = 0; i < n; i++) parent[i] = i;
}
public int find(int i) {
if (parent[i] != i) {
parent[i] = find(parent[i]); // Path Compression
}
return parent[i];
}
public boolean union(int i, int j) {
int rootI = find(i);
int rootJ = find(j);
if (rootI != rootJ) {
// Union by Rank
if (rank[rootI] > rank[rootJ]) {
parent[rootJ] = rootI;
} else if (rank[rootI] < rank[rootJ]) {
parent[rootI] = rootJ;
} else {
parent[rootJ] = rootI;
rank[rootI]++;
}
return true;
}
return false;
}
}
type DSU struct {
parent []int
rank []int
}
func NewDSU(n int) *DSU {
p := make([]int, n)
for i := range p { p[i] = i }
return &DSU{parent: p, rank: make([]int, n)}
}
func (d *DSU) Find(i int) int {
if d.parent[i] != i {
d.parent[i] = d.Find(d.parent[i]) // Path Compression
}
return d.parent[i]
}
func (d *DSU) Union(i, j int) bool {
rootI := d.Find(i)
rootJ := d.Find(j)
if rootI != rootJ {
// Union by Rank
if d.rank[rootI] > d.rank[rootJ] {
d.parent[rootJ] = rootI
} else if d.rank[rootI] < d.rank[rootJ] {
d.parent[rootI] = rootJ
} else {
d.parent[rootJ] = rootI
d.rank[rootI]++
}
return true
}
return false
}
4. Complexity Analysis
| Operation | Time | Space | Notes |
|---|---|---|---|
| Union | O(α(N)) | O(N) | Nearly constant time. |
| Find | O(α(N)) | O(N) | Amortized. |
α(N) is the Inverse Ackermann function. For all practical values of N (even universe size), α(N) ≤ 4.