AlgoMaster Logo

Accounts Merge

mediumFrequency7 min readUpdated June 23, 2026

Understanding the Problem

Two accounts belong to the same person if they share at least one email, and the relation is transitive: if account A shares an email with account B, and B shares an email with C, all three merge into one person even when A and C have no email in common.

A single round of pairwise comparisons cannot capture these chains. The structure that does is a graph: treat emails as nodes, let each account connect its emails, and every merged account is one connected component. Once the components are known, the rest is bookkeeping: collect each component's emails, sort them, and attach the name.

Key Constraints:

  • 1 <= accounts.length <= 1000 -> With up to 1000 accounts and at most 9 emails each, there are at most 9,000 emails in total. Connected-component techniques run in near-linear time on this size.
  • 2 <= accounts[i].length <= 10 -> Each account has at least one email and at most 9 emails (the first entry is the name). Email lists are small.
  • 1 <= accounts[i][j].length <= 30 -> Email strings are short, so hashing and comparison are cheap.

Approach 1: DFS on Email Graph

Intuition

If we think of each email as a node, and draw an edge between two emails whenever they appear in the same account, then finding merged accounts is the same as finding connected components in this graph.

Within a single account like ["John", "a@mail.com", "b@mail.com", "c@mail.com"], a, b, and c all belong together. Connecting every pair would add up to K^2 edges per account. Connecting each email to the first email in the account is enough: a-b, a-c. This star shape uses only K-1 edges, and connectivity is all that component detection needs, not direct edges between every pair.

Once the graph is built, we run DFS from each unvisited email, collecting all reachable emails into one group. Each group becomes one merged account. The DFS uses an explicit stack, so the traversal does not depend on recursion depth limits even when one component contains every email.

Algorithm

  1. Build an adjacency list: for each account, connect every email to the first email in that account (bidirectional edges).
  2. Also maintain a map from each email to its account name.
  3. Initialize a visited set.
  4. For each unvisited email, run DFS to collect all emails in that connected component.
  5. Sort the collected emails, prepend the account name, and add to the result.

Example Walkthrough

1Build graph: Account 1 edges: johnsmith <-> john_newyork
johnsmith@mail.com
:
[john_newyork@mail.com]
john_newyork@mail.com
:
[johnsmith@mail.com]
1/8

Code

Union Find produces the same grouping without materializing an adjacency list or running a traversal.

Approach 2: Union Find on Emails

Intuition

Union Find (also called Disjoint Set Union) maintains a partition of elements into disjoint groups and supports two operations: find the representative of an element's group, and union two groups into one. That matches this problem directly. Treat each email as an element and process accounts one at a time, unioning every email in an account with that account's first email.

After an account is processed, all of its emails share one root. When a later account contains an email that already belongs to some group, the union pulls that account's remaining emails into the same group. Root equality is transitive, so chains of shared emails across accounts merge without any explicit graph traversal. With path compression and union by rank, each operation costs nearly O(1). Union by rank also bounds every tree's height at O(log NK), so the recursive find stays shallow; path compression then flattens the chains it touches.

Algorithm

  1. Initialize a Union Find structure where each email is its own parent.
  2. For each account, union all emails in that account with the first email.
  3. After all unions, find the root of each email and group emails by their root.
  4. Sort each group, prepend the account name, and add to the result.

Example Walkthrough

1Initialize: each email is its own parent
johnsmith
:
johnsmith
john_newyork
:
john_newyork
1/7

Code

Approach 2 keys the Union Find on email strings, so the parent and rank maps hold one string entry per email and every operation hashes strings. The accounts themselves offer smaller identifiers: there are at most 1,000 of them, so integer indices from 0 to n-1 can serve as the Union Find elements, backed by two plain integer arrays.

Approach 3: Union Find on Account Indices

Intuition

Treat each account, not each email, as a Union Find element. Maintain a map from email to the index of the first account that contained it. While scanning account i, each email falls into one of two cases: the email is new, so record i as its owner, or the email was already seen in account j, which proves accounts i and j belong to the same person, so union the two indices.

After the scan, every email's merged group is find(owner), the root of the account that first owned it. Grouping emails by that root and reading the name from accounts[root][0] produces the answer. The email map still holds one entry per email (building the output requires touching every email anyway), but the Union Find shrinks from string-keyed hash maps with an entry per email to two integer arrays with an entry per account.

Algorithm

  1. Create parent and rank arrays of size n (the number of accounts), with each index as its own parent.
  2. For each account i and each of its emails: if the email already has an owner j, call union(i, j); otherwise record i as the email's owner.
  3. For every email in the map, compute root = find(owner) and append the email to that root's group.
  4. Sort each group, prepend accounts[root][0] as the name, and add it to the result.

Example Walkthrough

1Account 0 (John): johnsmith and john_newyork are new, owner = 0. parent = [0, 1, 2, 3]
johnsmith
:
0
john_newyork
:
0
parent
:
[0, 1, 2, 3]
1/5

Code