题目大意: 同一个昵称可能不是同一个人,也可能是同一个人,但不同的昵称肯定不是同一个人.按照题意将同一个人的邮箱地址链接起来
并查集:
对对应的邮箱地址进行并查集操作,如果存在有交集的邮箱地址,则两个列表肯定归属于同一个人,将他们连接起来.
1 class Solution { 2 public: 3 int find(int idr, vector<int>& u) { 4 while (idr != u[idr]) idr = u[idr]; 5 return idr; 6 } 7 void join(int idr1, int idr2, vector<int>& u) { 8 int f1 = find(idr1, u); 9 int f2 = find(idr2, u); 10 u[f2] = f1; 11 } 12 map<string, int> hashmap1; 13 map<int, vector<vector<string>>> hashmap2; 14 vector<vector<string>> res; //返回向量 15 vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) { 16 vector<int> u(accounts.size()); 17 for (int i = 0; i < u.size(); i++) u[i] = i; //初始化并查集 18 for (int k = 0; k < accounts.size(); k++) { //查找,逻辑连接 19 for (int i = 1;i<accounts[k].size();i++) { 20 auto addr = accounts[k][i]; 21 auto iter = hashmap1.find(addr); 22 if (iter == hashmap1.end()) hashmap1[addr] = k; 23 else join(hashmap1[addr], k, u); 24 } 25 } 26 27 //打印并查集情况 28 //for (int i = 0; i < u.size(); i++) { 29 // cout << u[i] << " "; 30 // for (auto val : accounts[i]) cout << val << " "; 31 // cout << endl; 32 //} 33 34 for (int i = 0; i < accounts.size(); i++) { //物理连接 35 int f = find(u[i], u); //对顶层节点进行分类 36 auto iter = hashmap2.find(f); 37 if (iter == hashmap2.end()) { //如果还不存在先创建一个 38 hashmap2[f] = {}; 39 } 40 hashmap2[f].push_back(accounts[i]); 41 } 42 for (auto iter = hashmap2.begin(); iter != hashmap2.end(); iter++) { 43 set<string> map; 44 for (auto list : iter->second) { 45 for (int i = 1;i<list.size();i++) { 46 string val = list[i]; 47 auto itr = map.find(val); 48 if (itr == map.end()) map.insert(val); 49 } 50 } 51 if (map.empty()) continue; 52 vector<string> temp(map.begin(), map.end()); 53 sort(temp.begin(), temp.end()); 54 temp.insert(temp.begin(), accounts[iter->first][0]); 55 res.push_back(temp); 56 } 57 return res; 58 } 59 };