Command Palette

Search for a command to run...

Problem 25.3 · Union-Find (DSU)Medium

Accounts Merge

What it teaches: Mapping strings to ids: union emails that appear in the same account, then group by root.

Practise it on judges as “Accounts Merge”.

The problem

Each account is [name, email1, email2, …]. Two accounts belong to the same person if they share any email. Merge them and return each person as [name, sorted emails…]. Accounts may be returned in any order.

Example 1

Input: [[John, johnsmith@mail.com, john_newyork@mail.com], [John, johnsmith@mail.com, john00@mail.com], [Mary, mary@mail.com], [John, johnnybravo@mail.com]]
Output: [[John, john00@mail.com, john_newyork@mail.com, johnsmith@mail.com], [Mary, mary@mail.com], [John, johnnybravo@mail.com]]

Constraints

  • 1 ≤ accounts ≤ 1000
  • Up to 10 emails each

Pattern clues in the wording

  • → Merge groups that share any member

These clues point to Union-Find: Keep each group as a tree with a root; find the root to test membership and link roots to merge groups.

Stuck? Take one hint at a time

Solution.java · starter
import java.util.*;

class Solution {
    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        return new ArrayList<>();
    }
}

Write your solution locally or in your editor for now. The in-browser runner (Java first, then Python, C++ and more) will run these tests right here.

Test cases

#InputExpected
1
accounts = [["John","johnsmith@mail.com","john_newyork@mail.com"],["John","johnsmith@mail.com","john00@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]]
[["John","john00@mail.com","john_newyork@mail.com","johnsmith@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]]

+ 1 hidden test the code runner will check

From slow to fast

Approaches

1

Union-find on emails

Time O(E log E) for sorting, E = total emails Space O(E)

Map email → id and email → name. Union each account's emails with its first one. Group emails by root into TreeSets, then prepend the name.

Approach 1
import java.util.*;

class Solution {
    private int[] parent;

    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        Map<String, Integer> id = new HashMap<>();
        Map<String, String> owner = new HashMap<>();
        for (List<String> acc : accounts)
            for (int i = 1; i < acc.size(); i++) {
                id.putIfAbsent(acc.get(i), id.size());
                owner.put(acc.get(i), acc.get(0));
            }
        parent = new int[id.size()];
        for (int i = 0; i < parent.length; i++) parent[i] = i;
        for (List<String> acc : accounts)
            for (int i = 2; i < acc.size(); i++)
                parent[find(id.get(acc.get(i)))] = find(id.get(acc.get(1)));
        Map<Integer, TreeSet<String>> groups = new HashMap<>();
        for (String email : id.keySet())
            groups.computeIfAbsent(find(id.get(email)), k -> new TreeSet<>()).add(email);
        List<List<String>> out = new ArrayList<>();
        for (TreeSet<String> emails : groups.values()) {
            List<String> row = new ArrayList<>();
            row.add(owner.get(emails.first()));
            row.addAll(emails);
            out.add(row);
        }
        return out;
    }

    private int find(int x) {
        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }
        return x;
    }
}

Verdict: Merging is near-linear; sorting dominates.

Before you submit

Edge cases and common mistakes

Test these inputs

  • Same name, different people (no shared email)
  • An account with one email

Mistakes people make

  • Merging by name.
  • Forgetting to sort emails within an account.

Interview

Follow-up questions

How would you do it with DFS?