[路飞]_LeetCode_765. 情侣牵手

153 阅读1分钟

题目

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
解释: 无需交换座位,所有的情侣都已经可以手牵手了。

来源:力扣(LeetCode)leetcode-cn.com/problems/co…

解题思路

  1. 这题也是连通性的问题,连通性的问题可以使用并查集解决;
  2. 把相邻座位上的两个情侣编号合并,情侣编号 = Math.floor(row[i] / 2)
  3. 统计并查集中父节点不是自己的节点个数,就是需要交换的次数;

代码实现

var minSwapsCouples = function (row) {
    const n = row.length
    const tot = n / 2
    const uf = new UnionFind(tot)

    //把相邻座位上的两个情侣编号合并
    //情侣编号 = row[i] / 2
    for (let i = 0; i < n; i += 2) {
        uf.union(Math.floor(row[i] / 2), Math.floor(row[i + 1] / 2))
    }

    let ans = 0

    //统计并查集中父节点不是自己的节点个数,就是需要交换的次数
    for (let i = 0; i < tot; i++) {
        if (uf.find(i) !== i) ans++
    }

    return ans
};

class UnionFind {
    constructor(n) {
        this.parent = new Array(n).fill(0).map((item, index) => index)
    }

    find(i) {
        return this.parent[i] = this.parent[i] !== i ? i : this.find(this.parent[i])
    }

    union(p, q) {
        this.parent[this.find(p)] = this.find(q)
    }
}

如有错误欢迎指出,欢迎一起讨论!