js(93)~[765] 情侣牵手-并查集

112 阅读1分钟

力扣本题传送门 image.png 这道题说的是困难,其实只要思路能够想明白,也不难,前提是并查集,掌握住了,但是我思路不清楚,并查集理解的也不是很到位,素以只能是跟着撸了一遍代码,

/*
 * @lc app=leetcode.cn id=765 lang=javascript
 *
 * 
 */

// @lc code=start
/**
 * @param {number[]} row
 * @return {number}
 */
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 minSwapsCouples = function (row) {
	/* 遍历row数组,每次都取出来两个人,默认情况下情侣的编号是从0开始的
	一对正确的情侣就是一个偶数和一个奇数;并且 奇数 = 偶数+1;以及 奇数/2 == 偶数/
	2;符合这样的条件才是正确的一对情侣
	否则,就需要将两个编号除以2之后的结果进行连通,进行交换次数。
	当n-1 对配对成功的时候,最后一对也会配对成功,我们只需要记录连通合并的次数。这就是需要调整的次数。 */
	const l = row.length;
	// 求情侣队
	const ls = l >> 1;
	const uf = new UnionFind(ls);

	// 每次循环2个
	for (let i = 0; i < l; i += 2) {
		// 拿到两个情侣进行联通
		uf.unite(row[i] >> 1, row[i + 1] >> 1)
	}
	// 情侣队 - 并查集的联通分量
	return ls - uf.getCount()

};
// @lc code=end