Browse curriculum

Accounts Merge

Merge the accounts that belong to one person, joined by any shared email, using union-find over emails and a final group-and-sort pass.

Problem Understanding

Accounts Merge (LeetCode 721): each account is a list whose first item is a name and whose other items are emails. Two accounts belong to the same person if they share at least one email. People can share a name, so a name alone never merges two accounts. Merge each person's accounts and return their emails in sorted order, with the name first. The accounts can come back in any order.

Example: [["John","johnsmith@mail.com","john_newyork@mail.com"],["John","johnsmith@mail.com","john00@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]] returns [["John","john00@mail.com","john_newyork@mail.com","johnsmith@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]]. The first two Johns share johnsmith@mail.com; the third John shares nothing and stays separate.

The Intuition: Emails Are the Nodes

Treat every email as a node. An account says all of its emails belong to one person, so it connects them. Two accounts that share an email end up in the same connected piece, even through a chain of other accounts. Each connected piece is one person.

  1. Register each email as its own set, and remember which name owns it.
  2. Union the account's first email with each of the others. That is enough to put the whole account in one set.
  3. Group by root. Emails with the same root belong to one person. Sort each group and put the name in front.

This is the same set-merging as Redundant Connection and Number of Provinces, with strings for nodes instead of numbers.

Interactive Walkthrough

GREEN = MERGED · COLOUR = PERSON

EMPTY MAPS

account

:

name

:

people

:

parent[email]

 

An empty parent map and owner map. Every email will start as its own set

Next

Account 1, John: js, jny. New emails js, jny start as their own sets. Now join js to the rest

Free preview: the first 4 of 13 steps

accounts

The emails are shortened so they fit in a node: js stands for johnsmith@mail.com. Green edges are unions that merged two sets. In the grouping pass every email takes its person's colour. Try Already joined: the third account's union finds the same root and changes nothing.

Dry Run Table

Input: John: js, jny; John: js, j00; Mary: m; John: jb (the example above, with shortened emails).

Account New emails Union parent change
1. John: js, jny js, jny find(js) = js, find(jny) = jny parent[jny] = js
2. John: js, j00 j00 find(js) = js, find(j00) = j00 parent[j00] = js
3. Mary: m m none (one email) none
4. John: jb jb none (one email) none

Grouping: js, jny and j00 have root js; m and jb are their own roots.

Result: [John, j00, jny, js], [Mary, m], [John, jb].

The Solution Template

Union-find keyed by email, with path halving in find(). The C version gives each distinct email a numeric id by sorting, which also leaves every group already sorted.

Accounts Merge Code
1var accountsMerge = function(accounts) {
2 const parent = new Map();
3 const owner = new Map();
4 const find = (x) => {
5 while (parent.get(x) !== x) {
6 parent.set(x, parent.get(parent.get(x)));
7 x = parent.get(x);
8 }
9 return x;
10 };
11
12 for (const [name, ...emails] of accounts) {
13 const first = emails[0];
14 for (const email of emails) {
15 if (!parent.has(email)) parent.set(email, email);
16 owner.set(email, name);
17 }
18 for (const email of emails.slice(1)) {
19 const a = find(first), b = find(email);
20 if (a !== b) {
21 parent.set(b, a);
22 }
23 }
24 }
25
26 const groups = new Map();
27 for (const email of parent.keys()) {
28 const root = find(email);
29 if (!groups.has(root)) groups.set(root, []);
30 groups.get(root).push(email);
31 }
32 return [...groups].map(([root, emails]) => [owner.get(root), ...emails.sort()]);
33};

Edge Cases & Common Mistakes

  • Same name, different people: never merge on the name. Only a shared email joins two accounts.
  • Account with one email: nothing to union; it still appears in the result, possibly merged through another account.
  • Chains: A shares an email with B and B with C, but A and C share nothing. They are still one person, which union-find handles and a pairwise comparison of accounts misses.
  • Unsorted output: each person's emails must be sorted; the name stays first and is not sorted with them.
  • Duplicate emails across accounts: register an email once. Resetting its parent when it shows up again would undo earlier unions.

Summary

Every email is a node. Union each account's first email with the rest, then group the emails by root, sort each group and put the owner's name in front. O(E log E) time for the sort, O(E) space.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Register

    For each account, give every new email its own set and remember the owner's name.

  2. Union

    Union the account's first email with each of its other emails.

  3. Group and sort

    Group every email by its root, sort each group and put the owner's name in front.

Frequently asked questions

Why union emails and not names?

Two people can share a name, so a name proves nothing. A shared email is the only thing that proves two accounts belong to one person, and the link can run through a chain of accounts. Union-find over emails follows those chains for you.


Why union only the first email with the others?

Joining the first email to each other email puts every email of the account in one set with k - 1 unions. Joining every pair would add nothing, because union-find already treats the set as connected.


What is the time complexity?

With E emails in total, the unions and finds are close to O(E) with path compression. Sorting each person's emails costs O(E log E), which dominates. The parent and owner maps take O(E) space.


Can I solve it with DFS instead?

Yes. Build a graph with an edge from each account's first email to its other emails, then run a DFS from every unvisited email to collect one person's emails. It is the same connected-components idea; union-find just builds the components as it reads.

New to the technique behind this problem? Watch it run step by step:

Topological Sort Visualization

Applying for software engineering roles? Free, no sign-up:

AI resume checker: match your resume to the job description