帳戶合併


題目概述


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

如今,咱們想合併這些帳戶。若是兩個帳戶都有一些共同的郵箱地址,則兩個帳戶一定屬於同一我的。請注意,即便兩個帳戶具備相同的名稱,它們也可能屬於不一樣的人,由於人們可能具備相同的名稱。一我的最初能夠擁有任意數量的帳戶,但其全部帳戶都具備相同的名稱。.net

合併帳戶後,按如下格式返回帳戶:每一個帳戶的第一個元素是名稱,其他元素是按字符 ASCII 順序排列的郵箱地址。帳戶自己能夠以任意順序返回。code

示例 1:blog

輸入:
accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"]]字符串

輸出: [["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary", "mary@mail.com"]]get

解釋:
第一個和第三個 John 是同一我的,由於他們有共同的郵箱地址 "johnsmith@mail.com"。
第二個 John 和 Mary 是不一樣的人,由於他們的郵箱地址沒有被其餘賬戶使用。
能夠以任何順序返回這些列表,例如答案 [['Mary','mary@mail.com'],['John','johnnybravo@mail.com'],
['John','john00@mail.com','john_newyork@mail.com','johnsmith@mail.com']] 也是正確的。博客

提示:it

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

解題思路

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

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

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);
        }
    }
}
相關文章
相關標籤/搜索