力扣本题传送门
这道题说的是困难,其实只要思路能够想明白,也不难,前提是并查集,掌握住了,但是我思路不清楚,并查集理解的也不是很到位,素以只能是跟着撸了一遍代码,
/*
* @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