N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手。 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起。 一次交换可选择任意两人,让他们站起来交换座位。
人和座位用 0 到 2N-1 的整数表示,情侣们按顺序编号,第一对是 (0, 1),第二对是 (2, 3),以此类推,最后一对是 (2N-2, 2N-1)。
这些情侣的初始座位 row[i] 是由最初始坐在第 i 个座位上的人决定的。
示例 1:
输入:row = [0, 2, 1, 3]
输出: 1
解释: 我们只需要交换row[1]和row[2]的位置即可。
示例 2:
输入:row = [3, 2, 0, 1]
输出: 0
解释: 无需交换座位,所有的情侣都已经可以手牵手了。
这道题我第一想法是使用map函数
-
将row中所有数都存入map,记录下标。
-
遍历row,判断同座位两个数是否符合。
-
不符合变找到符合的数,与当前数替换,在map中也替换。
-
同时记录替换的次数。
var minSwapsCouples = function (row) { let num = 0; let len = row.length let u = new UnionSet(len) let map = new Map() // 将下标存入map中 for (let i = 0; i < len; i++) { map.set(row[i], i) } // 按双数遍历 for (let i = 0; i < row.length; i = i + 2) { // 判断座位号 if (row[i] % 2 == 0) { // 判断是否是情侣 if (row[i] + 1 != row[i + 1]) { // 不是就去找对应的情侣,换座 let j = map.get(row[i] + 1); [row[i + 1], row[j]] = [row[j], row[i + 1]]; // 重新记录座位号 map.set(row[i + 1], i + 1) map.set(row[j], j) // HR尊次数加一 num++; } } else { // 理论同上 if (row[i + 1] != row[i] - 1) { let j = map.get(row[i] - 1); [row[i + 1], row[j]] = [row[j], row[i + 1]] map.set(row[i + 1], i + 1) map.set(row[j], j) num++; } } } console.log(num); return num > 0 ? num - 1 : num };
let j = map.get(row[i] + 1);必须加;,否则下面的交换会报错
但是这种方法在力扣上耗时非常严重,后来想到了用并查集的方法,将能组成情侣的组合看做一个并查集。
比如**[1,4,0,5,8,7,6,3,2,9]中[1,4,0,5]**就可以看做是一个并查集,因为经过交换,能组成情侣。**[8,7,6,3,2,9]**看做成一个并查集。我们查看一共有多少组情侣,多少个并查集,想减就是需要交换的次数。
var minSwapsCouples = function (row) {
// 人数
const len = row.length、
// 情侣数
const n = len / 2
const u = new UnionSet(n)
// 创建并查集
for (let i = 0; i < len; i += 2) {
const l = Math.floor(row[i] / 2)
const r = Math.floor(row[i + 1] / 2)
u.merge(l, r)
}
// 查看并查集数
let cnt = 0
for (let i = 0; i < n; i++) {
if (u.get(i) == i) cnt++
}
return n-cnt
};
class UnionSet {
constructor(n) {
this.fa = new Array(n + 1)
this.n = n
this.cnt = new Array(n + 1)
for (let i = 0; i < n; i++) {
this.fa[i] = i
this.cnt[i] = 1
}
}
get (x) {
return this.fa[x] = (this.fa[x] == x ? x : this.get(this.fa[x]))
}
merge (a, b) {
if (this.get(a) == this.get(b)) return
this.cnt[this.get(b)] += this.cnt[this.get(a)]
this.fa[this.get(a)] = this.get(b)
return
}
}