js(92)~721. 账户合并-并查集

128 阅读2分钟

力扣本题传送门 image.png

这个题用并查集没有错,但是这个逻辑比上一刀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