2021-01-08 721.账户合并[哈希表,并查集]

721.账户合并

思路一:哈希表,并查集

鉴于很多邮箱公用一个名字,我们只需要现将同一个人的邮箱汇总在一起,然后最后输出答案的时候,用他的一个邮箱反向查询到他对应的用户的名字即可。

官方源码分析:

class Solution {
    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        Map<String, Integer> emailToIndex = new HashMap<String, Integer>();
        Map<String, String> emailToName = new HashMap<String, String>();

		// 第一步:给每个不重复的邮箱一个编号和对应的名字
        int emailsCount = 0;
        for (List<String> account : accounts) {
            String name = account.get(0);
            int size = account.size();
            for (int i = 1; i < size; i++) {
                String email = account.get(i);
                if (!emailToIndex.containsKey(email)) {
                    emailToIndex.put(email, emailsCount++);
                    emailToName.put(email, name);
                }
            }
        }
        
        // 第二步:将每一条Entry中同一个人的邮箱统计在一起。
        UnionFind uf = new UnionFind(emailsCount);
        for (List<String> account : accounts) {
            String firstEmail = account.get(1);
            int firstIndex = emailToIndex.get(firstEmail);
            int size = account.size();
            for (int i = 2; i < size; i++) {
                String nextEmail = account.get(i);
                int nextIndex = emailToIndex.get(nextEmail);
                uf.union(firstIndex, nextIndex);
            }
        }

        // 第三步:🌟将所有同类的元素合并在一起!类别编号用index表示
        Map<Integer, List<String>> indexToEmails = new HashMap<Integer, List<String>>();
        // 利用keyset将所有的不重复的email取出来
        for (String email : emailToIndex.keySet()) {
            int index = uf.find(emailToIndex.get(email)); //找到email对应的类别编号
            // 利用getOrDefault,如果indexToEmails中存在index,就返回它存的List<String>,
            // 反之就返回一个新的List<>String>;
            List<String> account = indexToEmails.getOrDefault(index, new ArrayList<String>());
            account.add(email);
            indexToEmails.put(index, account);
        }

        // 第四步:整合为答案
        List<List<String>> merged = new ArrayList<List<String>>();
        // 得到每一个index对应的email集合
        for (List<String> emails : indexToEmails.values()) {
            Collections.sort(emails); //因为题目要求对邮箱进行排序
            String name = emailToName.get(emails.get(0));
            List<String> account = new ArrayList<String>();
            account.add(name);
            account.addAll(emails);
            merged.add(account);
        }
        return merged;
    }
}

class UnionFind {
    int[] parent;

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

    public void union(int index1, int index2) {
        parent[find(index2)] = find(index1);
    }

    public int find(int index) {
        if (parent[index] != index) {
            parent[index] = find(parent[index]);
        }
        return parent[index];
    }
}

自己手写:

收获:

  1. 可以利用getOrDefault创建一个新的HashMap;
    如下面的代码,就等同于如果index存在,就取出原来的List<String>并添加"新元素",
    如果index不存在,就为这个新的key index创建一个空的List<String>并添加“新元素”
    最后勿忘更新原来的HashMap。
Map<Integer,List<String>> map = new HashMap<>();
List<String>tmp = map.getOrDefault(index,new ArrayList<String>());
tmp.add("新元素");
map.put(index,tmp);
  1. 得到所有的key:.keySet(),得到每一个key对应的values集合.values()
  2. Collections.sort()可以对List<String>进行升序排序。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值