賬戶合併


題目概述


給定一個列表 accounts,每個元素 accounts[i] 是一個字符串列表,其中第一個元素 accounts[i][0] 是 名稱 (name),其餘元素是 emails,表示該賬戶的郵箱地址。

現在,我們想合併這些賬戶。如果兩個賬戶都有一些共同的郵箱地址,則兩個賬戶必定屬於同一個人。請注意,即使兩個賬戶具有相同的名稱,它們也可能屬於不同的人,因爲人們可能具有相同的名稱。一個人最初可以擁有任意數量的賬戶,但其所有賬戶都具有相同的名稱。

合併賬戶後,按以下格式返回賬戶:每個賬戶的第一個元素是名稱,其餘元素是按字符 ASCII 順序排列的郵箱地址。賬戶本身可以以任意順序返回。

示例 1:

輸入:
accounts = [["John", "[email protected]", "[email protected]"], ["John", "[email protected]"], ["John", "[email protected]", "[email protected]"], ["Mary", "[email protected]"]]

輸出: [["John", '[email protected]', '[email protected]', '[email protected]'], ["John", "[email protected]"], ["Mary", "[email protected]"]]

解釋:
第一個和第三個 John 是同一個人,因爲他們有共同的郵箱地址 "[email protected]"。
第二個 John 和 Mary 是不同的人,因爲他們的郵箱地址沒有被其他帳戶使用。
可以以任何順序返回這些列表,例如答案 [['Mary','[email protected]'],['John','[email protected]'],
['John','[email protected]','[email protected]','[email protected]']] 也是正確的。

提示:

  • accounts 的長度將在 [1,1000] 的範圍內。
  • accounts[i] 的長度將在 [1,10] 的範圍內。
  • accounts[i][j] 的長度將在 [1,30] 的範圍內。

解題思路

本題可以使用並查集解決,具體什麼是並查集,可以看看這篇博客 https://blog.csdn.net/bjweimengshu/article/details/108332389

根據題目要求,兩個賬戶只要有一個郵箱相同,那麼就認爲是同一個人,因此我們以下標表示用戶,把所有屬於同一個人的用戶(下標)使用並查集連接起來,接下來嘛 。。。我也不知道怎麼描述,看代碼吧

class Solution {

    public List<List<String>> accountsMerge(List<List<String>> accounts) {
    	// 創建一個 HashMap,通過下列的循環操作可以得知
    	// 最終每個郵箱都會對應它所屬的某一個用戶id
        Map<String, Integer> emailToId = new HashMap<>();
        int accountsLen = accounts.size();
        UnionFind union = new UnionFind(accountsLen);
        for(int i = 0; i < accountsLen; i++) {
            int emailsLen = accounts.get(i).size();
            for(int j = 1; j < emailsLen; j++) {
                String curEmail = accounts.get(i).get(j);
                if(emailToId.containsKey(curEmail)) {
                    union.merge(emailToId.get(curEmail), i);
                } else {
                    emailToId.put(curEmail, i);
                }
            }
        }
        // 將用戶id與其擁有的所有email對應起來
        Map<Integer, List<String>> idToEmail = new HashMap<>();
        for(Map.Entry<String, Integer> entry : emailToId.entrySet()) {
        	// 首先要找到父id
            int id = union.getFather(entry.getValue());
            // 父id擁有的emails一定是連接集合中所有用戶所共有的
            List<String> emails = idToEmail.getOrDefault(id, new LinkedList<>());
            // 再把缺少的email添加到emails中
            emails.add(entry.getKey());
            idToEmail.put(id, emails);
        }
        // 將id與用戶名對應即可
        List<List<String>> result = new LinkedList<>();
        for (Map.Entry<Integer,List<String>> entry : idToEmail.entrySet()) {
            List<String> list = entry.getValue();
            Collections.sort(list);
            list.add(0, accounts.get(entry.getKey()).get(0));
            result.add(list);
        }
        return result;
    }

    class UnionFind {
        int[] f;

        public UnionFind(int n) {
            f = new int[n];
            for(int i = 0; i < n; i++) {
                f[i] = i;
            }
        }

        public int getFather(int index) {
            return f[index] == index ? index : getFather(f[index]);
        }

        public void merge(int index1, int index2) {
            f[getFather(index1)] = getFather(index2);
        }
    }
}

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