721. 账户合并

给定一个列表 accounts,每个元素 accounts[i] 是一个字符串列表,其中第一个元素 accounts[i][0] 是 名称 (name),其余元素是 emails 表示该帐户的邮箱地址。

现在,我们想合并这些帐户。如果两个帐户都有一些共同的邮件地址,则两个帐户必定属于同一个人。请注意,即使两个帐户具有相同的名称,它们也可能属于不同的人,因为人们可能具有相同的名称。一个人最初可以拥有任意数量的帐户,但其所有帐户都具有相同的名称。

合并帐户后,按以下格式返回帐户:每个帐户的第一个元素是名称,其余元素是按顺序排列的邮箱地址。accounts 本身可以以任意顺序返回。

例子 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: 
  第一个和第三个 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']]仍然会被接受。

注意:

  • accounts的长度将在[1,1000]的范围内。
  • accounts[i]的长度将在[1,10]的范围内。
  • accounts[i][j]的长度将在[1,30]的范围内。

Review:

看到动态联通问题就要考虑是否应该用并查集算法解决,这个题我的思维很混乱,使用了大量字典,算法可能有漏洞,但是我也很佩服我自己在这么乱的思维下还可以一次ac且速度不慢

使用了TreeSet进行排序,不知道还有什么好方法


Code:

class Solution {
    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        final int len=accounts.size();
        int[] relation=new int[len];
        Map<String,Integer> dict = new HashMap<>();

        for (int i = 0; i < len; i++) {
            relation[i] = i;
            List<String> list = accounts.get(i);
            for (int j = 1; j < list.size(); j++) {
                Integer integer = dict.putIfAbsent(list.get(j), i);
                if (integer!=null){
                    union(relation,i,integer);
                }
            }
        }
        List<Set<String>> res = new ArrayList<>();
        int[] bos = new int[len];
        //遍历排序
        for (int i = 0; i < len; i++) {
            int find = find(relation, i);
            if (bos[find]==0){
                res.add(new TreeSet<>(accounts.get(i)));
                bos[find] = res.size();
            }else {
                Set<String> set = res.get(bos[find] - 1);
                set.addAll(accounts.get(i));
            }
        }
        //排序
        int i = 0;
        List<List<String>> result = new ArrayList<>();
        for (Set<String> re:res) {
            result.add(i++,new ArrayList<>(re));
        }
        return result;
    }


    private void union(int[] relation,int x ,int y){
        x = find(relation,x);
        y = find(relation,y);
        if (x!=y){
            relation[y] = x;
        }
    }

    private int find(int[] relation,int index){
        while (relation[index]!=index){
            index = relation[index];
        }
        return index;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值