leetcode 721. Accounts Merge FB-TAG

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", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@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 third John's are the same person as they have the common email "johnsmith@mail.com".
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', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'], 
['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] 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]

思路:第一想法是用hashmap, 不过貌似是我想太简单了,做了大半小时没做出来,就看了大神们的思路,fine, union-find, 我还不会,学呗。

看了好几篇,这个讲的不错:https://www.cnblogs.com/SeaSky0606/p/4752941.html


首先我们遍历每个账户和其中的所有邮箱,先将每个邮箱的root映射为其自身,然后将owner赋值为用户名。然后开始另一个循环,遍历每一个账号,首先对帐号的第一个邮箱调用find函数,得到其父串p,然后遍历之后的邮箱,对每个遍历到的邮箱先调用find函数,将其父串的root值赋值为p,这样做相当于将相同账号内的所有邮箱都链接起来了。我们下来要做的就是再次遍历每个账户内的所有邮箱,先对该邮箱调用find函数,找到父串,然后将该邮箱加入该父串映射的集合汇总,这样就我们就完成了合并。最后只需要将集合转为字符串数组,加入结果res中,通过owner映射找到父串的用户名,加入字符串数组的首位置,参见代码:

class Solution {
    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        List<List<String>> res = new ArrayList<List<String>>();
        Map<String, String> owner = new HashMap<>();
        Map<String, String> parents = new HashMap<>();
        Map<String, TreeSet<String>> unions = new HashMap<>();
        for(List<String>a : accounts){// 初始化。 
          for(int i=1;i < a.size();i++){
              parents.put(a.get(i), a.get(i));
                owner.put(a.get(i), a.get(0));
            }
        }
        for(List<String>a : accounts){// 将每个邮箱绑定到其父串
            String p = find(a.get(1), parents);
            System.out.print(p);
            for(int i=2;i<a.size();i++){
                 parents.put(find(a.get(i), parents),p);
            }
        }
          for(List<String> a : accounts){ //完成了合并
            String p = find(a.get(1), parents);
            if(!unions.containsKey(p)) unions.put(p, new TreeSet<>());
           for(int i = 1; i < a.size(); i++){
               unions.get(p).add(a.get(i));
        }
    }
        for (String p : unions.keySet()) {
            List<String> emails = new ArrayList(unions.get(p));
            emails.add(0, owner.get(p));
            res.add(emails);
        }
        return res;
    }
    public String find(String p, Map<String, String> parent) {
        while(p != parent.get(p)) {
            //path compression
            parent.put(p, parent.get(parent.get(p)));
            p = parent.get(p);
            System.out.print("2  "+p);
            
        }
        return p;
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值