原题地址(中等)

方法1—并查集+哈希表

思路

见力扣题解,写的真的好棒~

代码

  1. // 并查集模板
  2. class UnionFind {
  3. public:
  4. vector<int> parent;
  5. vector<int> rank;
  6. public:
  7. UnionFind(int _n): parent(vector<int>(_n)), rank(vector<int>(_n)) {
  8. for(int i=0; i<_n; i++)
  9. parent[i] = i;
  10. }
  11. int find(int x) {
  12. if(x != parent[x]) {
  13. parent[x] = find(parent[x]); // 路径压缩
  14. }
  15. return parent[x];
  16. }
  17. void merge(int x, int y) { // 按秩合并
  18. int rootx = find(x);
  19. int rooty = find(y);
  20. if(rootx != rooty) {
  21. if(rank[rootx] < rank[rooty]) swap(rootx, rooty);
  22. parent[rooty] = rootx;
  23. if(rank[rootx] == rank[rooty]) rank[rootx]++;
  24. }
  25. }
  26. };
  27. class Solution {
  28. public:
  29. vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) {
  30. vector<vector<string> > res;
  31. // 作用:存储每个邮箱属于哪个账户 ,同时 在遍历邮箱时,判断邮箱是否出现过
  32. // 格式:<邮箱,账户id>
  33. unordered_map<string, int> um;
  34. int n = accounts.size();
  35. UnionFind uf(n);
  36. for(int i = 0; i < n; i++) {
  37. int m = accounts[i].size();
  38. // 对每个邮箱,如果还未出现过,就放到哈希表中,否则将该账户与已经出现过该邮箱的账户合并
  39. for(int j = 1; j < m; j++) {
  40. string s = accounts[i][j];
  41. if(um.find(s) == um.end()) um[s] = i;
  42. else uf.merge(i, um[s]);
  43. }
  44. }
  45. // 作用: 存储每个账户下的邮箱
  46. // 格式: <账户id, 邮箱列表> >
  47. // 注意:umv的key必须是账户id,不能是账户名称,名称可能相同,会造成覆盖
  48. unordered_map<int, vector<string>> umv;
  49. for(auto& [k, v] : um) umv[uf.find(v)].emplace_back(k);
  50. for(auto& [k, v] : umv) {
  51. sort(v.begin(), v.end());
  52. vector<string> tmp(1, accounts[k][0]); // 名字
  53. tmp.insert(tmp.end(), v.begin(), v.end());
  54. res.emplace_back(tmp);
  55. }
  56. return res;
  57. }
  58. };