解題思路
這類「誰跟誰是一個小群體」的題目跟 union find 有關,這題額外加上還有 "name" 這一個標示群體名稱的字串。
解題分為四步,
step1: 初始化,每一個 email 的老大(parent)都是自己,並且記錄 email 的擁有者叫甚麼名字。
step2: 透過 find function,把每串除了第一個(本來就指向自己)的其餘的老大都指向第一個。在這個過程中,如果兩串都有同一個 email 出現,那自然會被歸在同一個群體之中(因為老大都一樣)。
step3: 先前只是記錄 email 跟對應的老大是誰。在 step3 要轉成 map 結構,一個老大 string 所屬的擁有者名字會對應到 set of other strings in the same group。做法是 traverse 每一個 email,map[老大].insert(自己)
step4: 依題目要求把 email 們先 sort,接著把名字加入即可。
這題好難,改天再寫一次。
程式碼
class Solution {
public:
string find(string email, unordered_map<string, string>& parent)
{
if(email != parent[email])
parent[email] = find(parent[email], parent); // compress
return parent[email];
}
vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) {
unordered_map<string, string> owner; // email's owner(email -> name)
unordered_map<string, string> parent; // email's parent for union
unordered_map<string, set<string>> unions; // answer
// Step 1
for (auto account : accounts) {
for (int i = 1; i < account.size(); i++) {
owner[account[i]] = account[0];
parent[account[i]] = account[i];
}
}
// Step 2
for (auto account : accounts) {
string p = find(account[1], parent);
for (int i = 2; i < account.size(); i++) {
parent[find(account[i], parent)] = p;
}
}
// Step 3
for (auto email : owner) {
unions[find(email.first, parent)].insert(email.first);
}
// Step 4
vector<vector<string>> result;
for (auto union_ : unions) {
vector<string> emails(union_.second.begin(), union_.second.end());
emails.insert(emails.begin(), owner[union_.first]);
result.push_back(emails);
}
return result;
}
};
沒有留言:
張貼留言