LeetCodee

721. Accounts Merge

Jump to Solution: Python Java C++ JavaScript C#

Problem Description

Given a list of accounts where each element accounts[i] is a list of strings, where the first element accounts[i][0] is a name, and the rest of the elements are emails representing emails of the account.

Now, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some common email to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name.

After merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails in sorted order. The accounts themselves can be returned in any order.

Examples:

Example 1:

Input: accounts = [["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"],["John","johnnybravo@mail.com"],["Mary","mary@mail.com"]]
Explanation:
The first and second John's are the same person as they have the common email "johnsmith@mail.com".
The third John and Mary are different people as none of their email addresses are used by other accounts.
We could return these lists in any order, for example the answer [['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'], 
['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] would still be accepted.

Example 2:

Input: accounts = [["Gabe","Gabe0@m.co","Gabe3@m.co","Gabe1@m.co"],["Kevin","Kevin3@m.co","Kevin5@m.co","Kevin0@m.co"],["Ethan","Ethan5@m.co","Ethan4@m.co","Ethan0@m.co"],["Hanzo","Hanzo3@m.co","Hanzo1@m.co","Hanzo0@m.co"],["Fern","Fern5@m.co","Fern1@m.co","Fern0@m.co"]]
Output: [["Ethan","Ethan0@m.co","Ethan4@m.co","Ethan5@m.co"],["Gabe","Gabe0@m.co","Gabe1@m.co","Gabe3@m.co"],["Hanzo","Hanzo0@m.co","Hanzo1@m.co","Hanzo3@m.co"],["Kevin","Kevin0@m.co","Kevin3@m.co","Kevin5@m.co"],["Fern","Fern0@m.co","Fern1@m.co","Fern5@m.co"]]

Constraints:

  • 1 ≤ accounts.length ≤ 1000
  • 2 ≤ accounts[i].length ≤ 10
  • 1 ≤ accounts[i][j].length ≤ 30
  • accounts[i][0] consists of English letters
  • accounts[i][j] (for j > 0) is a valid email

Python Solution

class Solution:
    def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:
        # Create graph of emails
        graph = defaultdict(set)
        email_to_name = {}
        
        for account in accounts:
            name = account[0]
            for email in account[1:]:
                graph[email].add(account[1])  # Connect to first email
                graph[account[1]].add(email)  # Connect back
                email_to_name[email] = name
        
        # DFS to find connected components
        visited = set()
        result = []
        
        for email in graph:
            if email not in visited:
                stack = [email]
                visited.add(email)
                emails = []
                
                while stack:
                    node = stack.pop()
                    emails.append(node)
                    for neighbor in graph[node]:
                        if neighbor not in visited:
                            visited.add(neighbor)
                            stack.append(neighbor)
                
                result.append([email_to_name[email]] + sorted(emails))
        
        return result

Implementation Notes:

  • Uses graph representation and DFS to find connected components
  • Time complexity: O(∑aᵢ log aᵢ) where aᵢ is the length of accounts[i]
  • Space complexity: O(∑aᵢ)

Java Solution

class Solution {
    public List> accountsMerge(List> accounts) {
        Map> graph = new HashMap<>();
        Map emailToName = new HashMap<>();
        
        for (List account : accounts) {
            String name = account.get(0);
            for (int i = 1; i < account.size(); i++) {
                String email = account.get(i);
                graph.computeIfAbsent(email, k -> new HashSet<>()).add(account.get(1));
                graph.computeIfAbsent(account.get(1), k -> new HashSet<>()).add(email);
                emailToName.put(email, name);
            }
        }
        
        Set visited = new HashSet<>();
        List> result = new ArrayList<>();
        
        for (String email : graph.keySet()) {
            if (!visited.contains(email)) {
                Stack stack = new Stack<>();
                stack.push(email);
                visited.add(email);
                List emails = new ArrayList<>();
                
                while (!stack.isEmpty()) {
                    String node = stack.pop();
                    emails.add(node);
                    for (String neighbor : graph.get(node)) {
                        if (!visited.contains(neighbor)) {
                            visited.add(neighbor);
                            stack.push(neighbor);
                        }
                    }
                }
                
                Collections.sort(emails);
                emails.add(0, emailToName.get(email));
                result.add(emails);
            }
        }
        
        return result;
    }
}

C++ Solution

class Solution {
public:
    vector> accountsMerge(vector>& accounts) {
        unordered_map> graph;
        unordered_map emailToName;
        
        for (const auto& account : accounts) {
            string name = account[0];
            for (int i = 1; i < account.size(); i++) {
                string email = account[i];
                graph[email].insert(account[1]);
                graph[account[1]].insert(email);
                emailToName[email] = name;
            }
        }
        
        unordered_set visited;
        vector> result;
        
        for (const auto& [email, _] : graph) {
            if (visited.find(email) == visited.end()) {
                stack st;
                st.push(email);
                visited.insert(email);
                vector emails;
                
                while (!st.empty()) {
                    string node = st.top();
                    st.pop();
                    emails.push_back(node);
                    for (const string& neighbor : graph[node]) {
                        if (visited.find(neighbor) == visited.end()) {
                            visited.insert(neighbor);
                            st.push(neighbor);
                        }
                    }
                }
                
                sort(emails.begin(), emails.end());
                emails.insert(emails.begin(), emailToName[email]);
                result.push_back(emails);
            }
        }
        
        return result;
    }
};

JavaScript Solution

/**
 * @param {string[][]} accounts
 * @return {string[][]}
 */
var accountsMerge = function(accounts) {
    const graph = new Map();
    const emailToName = new Map();
    
    for (const account of accounts) {
        const name = account[0];
        for (let i = 1; i < account.length; i++) {
            const email = account[i];
            if (!graph.has(email)) graph.set(email, new Set());
            if (!graph.has(account[1])) graph.set(account[1], new Set());
            graph.get(email).add(account[1]);
            graph.get(account[1]).add(email);
            emailToName.set(email, name);
        }
    }
    
    const visited = new Set();
    const result = [];
    
    for (const [email, _] of graph) {
        if (!visited.has(email)) {
            const stack = [email];
            visited.add(email);
            const emails = [];
            
            while (stack.length > 0) {
                const node = stack.pop();
                emails.push(node);
                for (const neighbor of graph.get(node)) {
                    if (!visited.has(neighbor)) {
                        visited.add(neighbor);
                        stack.push(neighbor);
                    }
                }
            }
            
            emails.sort();
            emails.unshift(emailToName.get(email));
            result.push(emails);
        }
    }
    
    return result;
};

C# Solution

public class Solution {
    public IList> AccountsMerge(IList> accounts) {
        var graph = new Dictionary>();
        var emailToName = new Dictionary();
        
        foreach (var account in accounts) {
            string name = account[0];
            for (int i = 1; i < account.Count; i++) {
                string email = account[i];
                if (!graph.ContainsKey(email)) graph[email] = new HashSet();
                if (!graph.ContainsKey(account[1])) graph[account[1]] = new HashSet();
                graph[email].Add(account[1]);
                graph[account[1]].Add(email);
                emailToName[email] = name;
            }
        }
        
        var visited = new HashSet();
        var result = new List>();
        
        foreach (var email in graph.Keys) {
            if (!visited.Contains(email)) {
                var stack = new Stack();
                stack.Push(email);
                visited.Add(email);
                var emails = new List();
                
                while (stack.Count > 0) {
                    string node = stack.Pop();
                    emails.Add(node);
                    foreach (var neighbor in graph[node]) {
                        if (!visited.Contains(neighbor)) {
                            visited.Add(neighbor);
                            stack.Push(neighbor);
                        }
                    }
                }
                
                emails.Sort();
                emails.Insert(0, emailToName[email]);
                result.Add(emails);
            }
        }
        
        return result;
    }
}

Implementation Notes:

  • Uses graph representation and DFS to find connected components
  • Time complexity: O(∑aᵢ log aᵢ) where aᵢ is the length of accounts[i]
  • Space complexity: O(∑aᵢ)