这个题用并查集没有错,但是这个逻辑比上一刀91的逻辑还是复杂,目前我还好立即不了,看助教讲解讲的我都蒙了,思路更是不对,所以这个就是跟着助教敲代码,敲了一遍也敲错了,找不到哪里错了,就这吧..
/*
* @lc app=leetcode.cn id=721 lang=javascript
*
* [721] 账户合并
*/
// @lc code=start
/**
* @param {string[][]} accounts
* @return {string[][]}
*/
class UnionFind {
constructor(n) {
this.parent = new Array(n).fill(0).map((v, i) => i);
this.size = new Array(n).fill(1);
this.count = n;
}
find(index) {
let root = this.parent[index];
if (root != index) {
root = this.find(root)
}
return root
}
unite(index1, index2) {
let root1 = this.find(index1), root2 = this.find(index2)
if (root1 === root2) {
return;
}
if (root1 < root2) {
[root1, root2] = [root2, root1]
}
this.parent[root2] = root1;
this.size[root1] += this.size[root2];
this.count--;
}
getCount() {
return this.count;
}
connected(index1, index2) {
return this.find(index1) === this.find(index2)
}
}
var accountsMerge = function (accounts) {
/* // 邮箱索引
const emailToIndex = new Map();
// 邮箱名称
const emailToName = new Map();
//初始化两桶分量 邮箱里面第几个出现
let emailsCount = 0;
//创建 邮箱坐标 邮箱名称的map表
for (const account of accounts) {
// 每一个子数组名称
const name = account[0];
const size = account.size;
// 从第一个开始拿到邮箱
for (let i = 1; i < size; i++) {
const email = account[i];
// 判断邮箱坐标里面有没有
if (!emailToIndex.has(email)) {
emailToIndex.set(email, emailsCount++);
emailToName.set(email, name)
}
}
}
// 根据邮箱数量,创建并查集
const uf = new UnionFind(emailsCount);
// 根据两个map 合并
for (const account of accounts) {
const firstEmail = account[1];
// 获取第一个邮箱的 在map的下表
const firstEmailIndex = emailToIndex.get(firstEmail);
const size = account.length;
for (let i = 0; i < size; i++) {
const nextEmail = account[i];
const nextEmailIndex = emailToIndex.get(nextEmail);
uf.unite(firstEmailIndex, nextEmailIndex)
}
}
//
const indexToEmails = new Map();
for (const email of emailToIndex.keys()) {
// 拿到祖先坐标
const index = uf.find(emailToIndex.get(email));
const account = indexToEmails.get(index) ? indexToEmails.get(index) : [];
account.push(email);
// 根据祖先坐标分组
indexToEmails.set(index, account)
}
// 用户之间的合并
const merged = []
for (const emails of indexToEmails.values()) {
emails.sort();
const name = emailToName.get(emails[0]);
const account = [];
account.push(name);
account.push(...emails);
merged.push(account);
}
return merged; */
const emailToIndex = new Map();
const emailToName = new Map();
let emailsCount = 0;
for (const account of accounts) {
const name = account[0];
const size = account.length;
for (let i = 1; i < size; i++) {
const email = account[i];
if (!emailToIndex.has(email)) {
emailToIndex.set(email, emailsCount++);
emailToName.set(email, name);
}
}
}
const uf = new UnionFind(emailsCount);
for (const account of accounts) {
const firstEmail = account[1];
const firstIndex = emailToIndex.get(firstEmail);
const size = account.length;
for (let i = 2; i < size; i++) {
const nextEmail = account[i];
const nextIndex = emailToIndex.get(nextEmail);
uf.unite(firstIndex, nextIndex);
}
}
const indexToEmails = new Map();
for (const email of emailToIndex.keys()) {
const index = uf.find(emailToIndex.get(email));
const account = indexToEmails.get(index) ? indexToEmails.get(index) : [];
account.push(email);
indexToEmails.set(index, account);
}
const merged = [];
for (const emails of indexToEmails.values()) {
emails.sort();
const name = emailToName.get(emails[0]);
const account = [];
account.push(name);
account.push(...emails);
merged.push(account);
}
return merged;
};
// @lc code=end