
分析
- 有题意可知,我们要合并的是每一个accounts[i],如果邮箱相同则属于同一个账号。
- 通过emailToIdx建立邮箱和accounts的下标i的映射关系,如果有邮箱相同我们就建立下标i的并查集;
- 遍历accounts数组,找到并查集中的每个根节点,如果根节点不存在则说明是新的节点,否则是需要合并的节点;
function accountsMerge(accounts) {
const emailToIdx = {};
const n = accounts.length;
const uf = new UF(n);
for (let i = 0; i < n; i++) {
const emails = accounts[i];
for (let j = 1; j < emails.length; j++) {
if (emailToIdx[emails[j]] == undefined) {
emailToIdx[emails[j]] = i;
} else {
uf.union(i, emailToIdx[emails[j]]);
}
}
}
const res = [];
for (let i = 0; i < n; i++) {
const parentIdx = uf.find(i);
if (!res[parentIdx]) {
const [name, ...emails] = accounts[i];
const arr = [...new Set(emails)].sort();
res[parentIdx] = [name, ...arr];
} else {
const [name, ...oldEmails] = res[parentIdx];
const [, ...newEmails] = accounts[i];
const arr = [...new Set([...oldEmails, ...newEmails])].sort();
res[parentIdx] = [name, ...arr];
}
}
return res.filter(Boolean);
}
class UF {
count = 0;
size = [];
parent = [];
constructor(n) {
this.count = n;
this.parent = [];
this.size = [];
for (let i = 0; i < n; i++) {
this.parent[i] = i;
this.size[i] = 1;
}
}
union(x, y) {
const xr = this.find(x);
const yr = this.find(y);
if (xr === yr) return;
if (this.size[xr] < this.size[yr]) {
this.parent[xr] = yr;
this.size[yr] += this.size[xr];
} else {
this.parent[yr] = xr;
this.size[xr] += this.size[yr];
}
this.count--;
}
isConnected = (x, y) => this.find(x) === this.find(y);
find(x) {
while (x !== this.parent[x]) {
this.parent[x] = this.parent[this.parent[x]];
x = this.parent[x];
}
return x;
}
count() {
return this.count;
}
}