Accounts Merge

Given a list accounts, 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 email that is common 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.

Example 1:

Input: 
accounts = [["John", "[email protected]", "[email protected]"], ["John", "[email protected]"], ["John", "[email protected]", "[email protected]"], ["Mary", "[email protected]"]]
Output: [["John", '[email protected]', '[email protected]', '[email protected]'],  ["John", "[email protected]"], ["Mary", "[email protected]"]]
Explanation: 
The first and third John's are the same person as they have the common email "[email protected]".
The second 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', '[email protected]'], ['John', '[email protected]'], 
['John', '[email protected]', '[email protected]', '[email protected]']] would still be accepted.

 

Note:

  • The length of accounts will be in the range [1, 1000].
  • The length of accounts[i] will be in the range [1, 10].
  • The length of accounts[i][j] will be in the range [1, 30].

思路:經典的union find題目。注意:此時union find的是accounts的index,0,1,2,如果後面email有相同的,則這一行的index應該union爲parents的。然後再根據index相同來收集emails。看懂了之後,再自己寫就好寫了,算法關鍵還是懂原理,代碼都是其次的。

class Solution {
    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        if(accounts == null || accounts.size() == 0) {
            return new ArrayList<List<String>>();
        }
        int[] parents = new int[accounts.size()];
        for(int i=0; i<accounts.size(); i++){
            parents[i] = i;
        }
        
        HashMap<String, Integer> owners = new HashMap<String, Integer>();
        for(int i=0; i<accounts.size(); i++){
            for(int j=1; j<accounts.get(i).size(); j++){
                String email = accounts.get(i).get(j);
                if(!owners.containsKey(email)){
                    owners.put(email, i);
                } else {
                    // if contains same email, union parent index;
                    int person = owners.get(email);
                    int rootP = findParent(parents, person);
                    int rootQ = findParent(parents, i);
                    if(rootP != rootQ){
                        parents[rootP] = rootQ;
                    }
                }
            }
        }
        
        // group emails belongs to same root;
        HashMap<Integer, TreeSet<String>> users = new HashMap<Integer, TreeSet<String>>();
        for(int i=0; i<accounts.size(); i++){
            if(users.containsKey(i)){
                users.get(i).addAll(accounts.get(i).subList(1, accounts.get(i).size()));
            } else {
                int parent = findParent(parents, i); // 應該用parent的index來收集,這個很容易弄錯。
                TreeSet<String> set = new TreeSet<String>();
                users.putIfAbsent(parent, set); // 這裏應該提前加入一個空的,後面好寫.
                List<String> emails = accounts.get(i);
                users.get(parent).addAll(emails.subList(1,emails.size())); 
            }
        }
        
        // construct result;
        List<List<String>> result = new ArrayList<List<String>>();
        for(Integer i: users.keySet()){
            String name = accounts.get(i).get(0);
            List<String> list = new ArrayList<>(users.get(i));
            list.add(0, name);
            result.add(list);
        }
        return result;
    }
    
    public int findParent(int[] parents, int i){
        while(i!=parents[i]){
            parents[i] = parents[parents[i]]; // Path compression. Princeton 算法課上學的。
            i = parents[i];
        }
        return i;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章