721. Accounts Merge
Input:
accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"]]
Output: [["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary", "mary@mail.com"]]
Explanation:
The first and third John's are the same person as they have the common email "johnsmith@mail.com".
The second John and Mary are different people as none of their email addresses are used by other accounts.
We could return these lists in any order, for example the answer [['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'],
['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] would still be accepted.// Union Find Method
string getRoot(unordered_map<string, string>& root, string s) {
return root[s] == s ? s : root[s] = getRoot(root, root[s]);
}
vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) {
vector<vector<string> > res;
unordered_map<string, string> root, owner;
unordered_map<string, set<string>> unions; // root email address -> email addresses
// Initialize root and owner
for (auto& account : accounts) {
for (int i = 1; i < account.size(); ++i) {
root[account[i]] = account[i];
owner[account[i]] = account[0];
}
}
// Connect email addresses with the smae account name
for (auto& account : accounts) {
string parent = getRoot(root, account[1]);
for (int i = 2; i < account.size(); ++i) {
root[getRoot(root, account[i])] = parent;
}
}
// Set unions
for (auto& account : accounts) {
for (int i = 1; i < account.size(); ++i) {
unions[getRoot(root, account[i])].insert(account[i]);
}
}
// Get the final result
for (auto& a : unions) {
vector<string> emails(a.second.begin(), a.second.end());
emails.insert(emails.begin(), owner[a.first]);
res.push_back(emails);
}
return res;
}Last updated