Home
Day 10 · Week 2

Union-Find Applications

Level 3 · Union-Find  ·  2 hrs: ~45 min theory · ~60 min code · ~15 min notes

🧠 Mental Model

With the optimized DSU in hand, the skill now is recognizing when a problem is Union-Find in disguise. The tell: you're incrementally merging groups and asking about connectivity, cycles, or component sizes — often as edges stream in, or where a graph traversal would be recomputed too many times.

Three canonical patterns cover the vast majority of interview questions.

⚙️ Pattern 1 — Cycle Detection (undirected)

Process edges one by one. For edge (u, v), if find(u) == find(v) before you union them, adding this edge closes a cycle.

Why it works An edge (u,v) creates a cycle iff u and v are already connected by a path — which is exactly find(u) == find(v). Each successful union reduces the component count by one; in a forest of n nodes you can add at most n−1 edges before some edge must connect two nodes already in the same tree.
Directed graphs are different: Union-Find detects cycles only in undirected graphs. For directed cycle detection use DFS 3-coloring (Week 3, Day 12).

⚙️ Pattern 2 — Kruskal's MST Prep

Tomorrow's Kruskal (Day 13) is literally: sort edges by weight, then add each edge iff it doesn't form a cycle (i.e. union returns true). Union-Find is the engine that makes the greedy cycle test O(α(n)) per edge.

Kruskal invariant: at every step the accepted edges form a forest (acyclic), and greedily choosing the cheapest safe edge preserves the existence of an optimal MST containing the current forest (the cut property — proven Day 13).

⚙️ Pattern 3 — Grouping / Merging Entities

"Merge accounts by shared email," "friends of friends," "islands as things connect over time." Map each entity to an index, union on every relationship, then read off groups by root. When new connections stream in and you must answer queries between them, DSU beats re-running BFS every time.

Union by size shines here: componentSize(x) answers "how big is this group" for free — a very common follow-up.

💻 Reference Implementation (Java)

Cycle detection using the optimized DSU from Day 9.

/** Returns true if adding edges introduces a cycle (undirected). */
public boolean hasCycle(int n, int[][] edges) {
    UnionFind uf = new UnionFind(n);   // Day 9 class
    for (int[] e : edges) {
        // union returns false when both ends already share a root
        if (!uf.union(e[0], e[1])) return true;
    }
    return false;
}

/** Kruskal skeleton — the Day 13 payoff, shown for context. */
public int kruskal(int n, int[][] edges) {
    Arrays.sort(edges, (a, b) -> a[2] - b[2]); // by weight
    UnionFind uf = new UnionFind(n);
    int total = 0, used = 0;
    for (int[] e : edges) {
        if (uf.union(e[0], e[1])) {  // safe (no cycle) → take it
            total += e[2];
            if (++used == n - 1) break; // MST complete
        }
    }
    return total;
}

⚠️ Common Pitfalls

Using DSU for directed cycles: it only models undirected connectivity. Don't reach for it in DAG/topo problems.
Mapping strings to indices sloppily: for account/email merges, keep a consistent Map<String,Integer> so every occurrence maps to the same node.
Re-running from scratch: if the problem streams unions and interleaves queries, keep one DSU alive — don't rebuild.

🎭 Problem Variances — Union-Find applications cheat-sheet

Consolidating the three patterns above into a fast-recognition table of the disguises Big Tech uses:

Disguise / phrasingWhat's really askedTwist to handle
"Detect the edge that creates a cycle" (undirected)Cycle detectionunion() returns false = cycle edge
"Merge accounts by shared email"Grouping by shared attributeMap strings→ids; union on shared key; group by root
"Earliest time everyone connected"Watch components → 1Sort by time, union, stop when count == 1
"Islands II — land added over time"Streaming connectivityAdd cell, union with land neighbors, track count
"Min cost to connect all" (setup for MST)Kruskal engineSort edges, union safe ones (Day 13)
"Regions cut by slashes / grid partitions"Components on a subdivided gridSplit each cell into parts, union carefully
"Directed cycle / dependency"NOT Union-FindUse DFS 3-color / Kahn (Week 3)
Trap to avoid: Union-Find models undirected connectivity only. The moment a problem is about directed dependencies or ordering, switch to topological sort / DFS coloring (Week 3).

🎯 Problems

LC 721 Accounts Merge Union accounts sharing any email; group emails by root, then sort. Med
LC 305 Number of Islands II Streaming land additions — DSU with dynamic component count. Classic incremental use. Hard
LC 1101 The Earliest Moment When Everyone Become Friends Sort by timestamp, union, and report when componentCount() hits 1. Med

📚 References