Union-find

Topics in this section
2 cards

Union-find: which group is this in?

Union-find (disjoint-set union) tracks items split into non-overlapping groups and answers one question fast: are these two items in the same group? It supports two operations. find(x) returns the group's representative, its root. union(a, b) merges two groups by pointing one root at the other.

Each group is a small tree stored in a plain array of parent indexes. Two tricks keep the trees nearly flat: union by size (hang the smaller tree under the larger) and path compression (after a find, point every node on the path straight at the root). With both, each operation costs almost O(1) on average.

Three groups as small trees with highlighted roots; union points one root at another
In real life

Merging customer records that share an email or a phone number into one person; finding which machines in a network can reach each other; detecting whether adding a road creates a loop (used in Kruskal's minimum spanning tree).

In code: Python · Rust
class DSU:
    def __init__(self, n):
        self.parent, self.size = list(range(n)), [1] * n
    def find(self, x):
        while self.parent[x] != x:
            self.parent[x] = self.parent[self.parent[x]]  # path halving
            x = self.parent[x]
        return x
    def union(self, a, b):
        ra, rb = self.find(a), self.find(b)
        if ra == rb: return False          # already together
        if self.size[ra] < self.size[rb]: ra, rb = rb, ra
        self.parent[rb] = ra               # smaller under larger
        self.size[ra] += self.size[rb]
        return True
  • Path halving (shown) is a one-line form of path compression.
  • Neither standard library has union-find; it's short enough that people write it from memory.
Check yourself

Customer records should be merged whenever they share an email or a phone number, even through a chain (A shares an email with B, B shares a phone with C). Which structure fits?

What union-find can't do

Union-find only ever merges. There's no cheap way to split a group again or remove an item: the trees don't remember which union created which link. If groups need to split, you rebuild from scratch or use a different structure.

It also only answers 'same group?', 'how big is the group?' and, with a counter, 'how many groups are there?'. It doesn't know the path between two items or the edges that connected them; for that you need the graph itself and a search.

In real life

If two customer records were merged by mistake, union-find can't undo just that link. Systems that need undo keep the list of matching pairs and rebuild the groups when something changes.

Check yourself

Which question can union-find NOT answer on its own?