January 06, 2020

721. Accounts Merge

721. Accounts Merge

Graph Connected Components的题目。We can use both union-find and DFS algorithms.

Sol 1. DFS

Referred to this post and this video solution.

Treat each email accounts group (an entity in the given input accounts) as a component, we want to find all connected components among these email accounts. Two components are connected if they have any emails in common.

class Solution {
    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        Map<String, Set<String>> graph = new HashMap<>();  // <email node, neighbor nodes>
        Map<String, String> emailToName = new HashMap<>();  // <email, name>
        buildGraph(graph, emailToName, accounts);
        List<List<String>> res = new ArrayList<>();
        Set<String> visited = new HashSet<>();
        // DFS search the graph;
        for (String mail : emailToName.keySet()) {
            if (!visited.contains(mail)) {
                visited.add(mail);
                List<String> list = new ArrayList<>();
                list.add(mail);
                dfs(graph, list, mail, visited);
                Collections.sort(list);
                list.add(0, emailToName.get(mail));
                res.add(list);
            }
        }
        return res;
    }
    
    // For each account, draw the edge from the first email to all other emails. 
    // Additionally, we'll remember a map from emails to names on the side. 
    private void buildGraph(Map<String, Set<String>> graph, Map<String, String> emailToName, List<List<String>> accounts) {
        for (List<String> account : accounts) {
            String name = account.get(0);
            for (int i = 1; i < account.size(); i++) {
                String mail = account.get(i);
                emailToName.put(mail, name);
                graph.putIfAbsent(mail, new HashSet<>());
                if (i == 1) {
                    continue;
                }
                String prev = account.get(i - 1);
                graph.get(prev).add(mail);
                graph.get(mail).add(prev);
            }
        }
        
    }
    
    // After finding each connected component using a depth-first search, we'll add that to our answer.
    private void dfs(Map<String, Set<String>> graph, List<String> list, String mail, Set<String> visited) {
        if (graph.get(mail) == null || graph.get(mail).size() == 0) {
            return;
        }
        for (String neighbor : graph.get(mail)) {
            if (!visited.contains(neighbor)) {
                visited.add(neighbor);
                list.add(neighbor);
                dfs(graph, list, neighbor, visited);
            }
        }
    }
}

Sol 2. Union Find

TODO. To refer to this post.

comments powered by Disqus