721. 账户合并
知识点:并查集
时间:2021年1月18日
题目链接
题目
给定一个列表 accounts,每个元素 accounts[i] 是一个字符串列表,其中第一个元素 accounts[i][0] 是 名称 (name),其余元素是 emails 表示该账户的邮箱地址。
现在,我们想合并这些账户。如果两个账户都有一些共同的邮箱地址,则两个账户必定属于同一个人。请注意,即使两个账户具有相同的名称,它们也可能属于不同的人,因为人们可能具有相同的名称。一个人最初可以拥有任意数量的账户,但其所有账户都具有相同的名称。
合并账户后,按以下格式返回账户:每个账户的第一个元素是名称,其余元素是按顺序排列的邮箱地址。账户本身可以以任意顺序返回。
示例 1:
输入:
accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"]]
输出:
[["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary", "mary@mail.com"]]
解释:
第一个和第三个 John 是同一个人,因为他们有共同的邮箱地址 "johnsmith@mail.com"。
第二个 John 和 Mary 是不同的人,因为他们的邮箱地址没有被其他帐户使用。
可以以任何顺序返回这些列表,例如答案 [['Mary','mary@mail.com'],['John','johnnybravo@mail.com'],
['John','john00@mail.com','john_newyork@mail.com','johnsmith@mail.com']] 也是正确的
提示:
- accounts的长度将在[1,1000]的范围内。
- accounts[i]的长度将在[1,10]的范围内。
- accounts[i][j]的长度将在[1,30]的范围内。
解题思路
- 用hashmap存储 邮箱和人的对应关系
- 遍历所有邮箱 如果这个邮箱第一次出现 则放入hashmap中 这个邮箱属于用户 这里用户用所对应的下标表示 省去再次构建 用户转换成int类型
- 如果这个邮箱已经出现过了 则合并这个用户对应下标 和 之前出现过的邮箱对应的用户下标 说明这两个是同一个用户
- 遍历所有用户和邮箱 找到祖先节点 把用户和邮箱关联起来放在 hashmap<int,set> 中 最后转换为答案
代码
#include "cheader.h"
class Solution {
public:
struct UN{
vector<int> ancestor;
UN(int x){
ancestor.resize(x);
for(int i = 0;i < x;i++)
ancestor[i] = i;
}
int find(int x){
if(ancestor[x] == x)
return x;
else
return ancestor[x] = find(ancestor[x]);
}
void merge(int a, int b){
ancestor[find(a)] = find(b);
}
};
vector<vector<string>> accountsMerge(vector<vector<string>>& accounts) {
unordered_map<string, int> um;
int n = accounts.size();
UN un = UN(n);
for(int i = 0; i< n; i++){
for(int j = 1; j< accounts[i].size(); j++){
if(um.find(accounts[i][j]) == um.end())
um[accounts[i][j]] = i; //记录mail对应的下标
else
un.merge(i, um[accounts[i][j]]);//如果出现过,合并i和上一次出现的位置
}
}
unordered_map<int, set<string>> umans;
for(int i = 0; i< n; i++){
int parent = un.find(i); //找到父节点
for(int j = 1;j < accounts[i].size(); j++)
umans[parent].insert(accounts[i][j]); //有相同邮箱的人 他们对应的下标属于一个连通分量 他们所有的邮箱放在一起
}
vector<vector<string>> ans;
for(auto it:umans){
vector<string> tmp;
tmp.push_back(accounts[it.first][0]);
for(string mail:it.second)
tmp.push_back(mail);
ans.push_back(tmp);
}
return ans;
}
};
int main()
{
vector<vector<string>> accounts;
accounts.push_back(vector<string>{"John", "johnsmith@mail.com", "john00@mail.com"});
accounts.push_back(vector<string>{"John", "johnnybravo@mail.com"});
accounts.push_back(vector<string>{"John", "johnsmith@mail.com", "john_newyork@mail.com"});
accounts.push_back(vector<string>{"Mary", "mary@mail.com"});
Solution s;
vector<vector<string>> ans = s.accountsMerge(accounts);
for(vector<string> x:ans){
for(string str:x)
cout<<str<<" ";
cout<<endl;
}
return 0;
}
今天也是爱zz的一天哦!