• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

RomanLin

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【并查集】LeetCode 721.账户合并

题解

对于\(vector<vector<string>> accounts\),我们定义\(accounts[i]\)为一个列表项。对于\(accounts\)中的一条列表项,第一个元素代表用户名称,其余元素均代表该用户所拥有的邮箱地址。如下图所示,是一个具有三条列表项的\(accounts\):

对于一个用户名称,其拥有的邮箱地址,不妨视为一个不包含重复元素的集合。当且仅当列表项之间的邮箱地址集合有交集时,可以合并列表项。
不妨假设\(n = accounts.size()\),那么本质就是问这\(n\)条列表项在所有具有交集的列表项进行合并后的集合信息。
可以用并查集维护\(n\)个不同的集合。
对于第\(i(0 \leq i \leq n-1)\)条列表项,易知该条列表项的邮箱地址都曾出现于第\(i\)个邮箱地址集合中。
那么不妨用\(map<string, vector<int>>\)维护邮箱地址出现过的集合序号,结果只需要将全部集合序号所指的集合合并为一个集合,最后的结果就是所求答案。
例如上述给出的图片,其集合序号信息如下:

邮箱地址1

1

邮箱地址2

1 2

邮箱地址3

1

邮箱地址4

2

邮箱地址5

2

邮箱地址6

3

由邮箱地址2 {1, 2},可知集合1和集合2是具有交集的,可以合并,并且可以证明,除此之外再无其他集合有交集。进行合并后,集合信息为:

  • 1(2) {邮箱地址1, 邮箱地址2, 邮箱地址3, 邮箱地址4, 邮箱地址5};
  • 3 {邮箱地址6}。

参考代码

class Solution {
public:
    void merge(vector<int> &bcj, int a, int b) {
        bcj[find(bcj, a)] = find(bcj, b);
    }

    int find(vector<int> &bcj, int x) {
        while (x != bcj[x]) {
            return bcj[x] = find(bcj, bcj[x]);
        }
        return x;
    }

    vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) {
        vector<vector<string>> ans;
        map<string, vector<int>> mp;
        int n = accounts.size();
        vector<int> bcj(n);
        iota(bcj.begin(), bcj.end(), 0);
        for (int i = 0; i < n; ++ i) {
            for (int j = 1; j < accounts[i].size(); ++ j) {
                mp[accounts[i][j]].emplace_back(i);
            }
        }
        for (auto &it: mp) {
            vector<int> &v = it.second;
            int len = v.size();
            for (int i = 1; i < len; ++ i) {
                merge(bcj, v[0], v[i]);
            }
        }
        map<int, set<string>> res;
        for (int i = 0; i < n; ++ i) {
            int anc = find(bcj, i);
            for (int j = 1; j < accounts[i].size(); ++ j) {
                res[anc].insert(accounts[i][j]);
            }
        }
        for (auto &it: res) {
            vector<string> vec;
            vec.emplace_back(accounts[it.first][0]);
            vec.insert(vec.end(), it.second.begin(), it.second.end());
            ans.emplace_back(vec);
        }
        return ans;
    }
};

posted on 2024-07-16 00:20  RomanLin  阅读(40)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3