题目大意:给出一些账户和账户下的邮箱,将同一账户的邮箱合并
分析:并查集应用。将邮箱作为并查集中的点,初始化每个邮箱是自己的父节点,然后查找合并,最后按格式输出。注意find函数做了路径压缩,可以提高查找效率。
代码:
class Solution {
public:
vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) {
map<string, string> owner; // map from the 邮箱 to 名字
map<string, string> parents; // map from an 邮箱 to its 邮箱的父亲
map<string, set<string>> unions; // the unions of accounts 并查集string下的结点们
for (int i = 0; i < accounts.size(); ++i) { //初始化
for (int j = 1; j < accounts[i].size(); ++j) {
parents[accounts[i][j]] = accounts[i][j]; // initialize as itself
owner[accounts[i][j]] = accounts[i][0];
}
}
for (int i = 0; i < accounts.size(); ++i) { // find and union 查找与合并
string ancestor = find(accounts[i][1], parents);
for (int j = 2; j < accounts[i].size(); ++j) {
parents[find(accounts[i][j], parents)] = ancestor;
}
}
for (int i = 0; i < accounts.size(); ++i) { //将每个邮箱结点放入它的根节点带领的并查集中
for (int j = 1; j < accounts[i].size(); ++j) {
unions[find(accounts[i][j], parents)].insert(accounts[i][j]);
}
}
vector<vector<string>> res;
for (auto p : unions) { //取出每一个map对
vector<string> emails(p.second.begin(), p.second.end());
emails.insert(emails.begin(), owner[p.first]); //在emails.begin()前面插入owner[p.first]元素
res.push_back(emails);
}
return res;
}
private:
string find(string s, map<string, string> &p) {
if(p[s] != s) p[s] = find(p[s],p);
return p[s];
}
};