[路飞]_情侣牵手

273 阅读2分钟

765. 情侣牵手

题目

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]的位置即可。

题解

贪心

  • 既然情侣必须相邻,假设任意情侣分别为甲、乙
  • 枚举数组,遇到情侣不相邻,帮当前的情侣甲找到情侣乙
  • 怎么帮?
  • 比如遇到了情侣4,他需要5坐在他下一位置,你把5从茫茫人海中找到不就完了。
  • 怎么找?
  • 比如数组[4,2,0,1,3,5]
  • 第1位是4,需要把5放在第2位;但是5在第6位,把第6位与第2位交换得到[4,5,0,1,3,2]
  • 然后情侣[4,5]就坐好了,再接着在[4,5,0,1,3,2]第3位开始
  • 第3位是0,第4位是1;他俩是情侣,不需要
  • 第5位是3,第6位是2,又是情侣,不需要交换
  • 整个过程交换1次答案1;
  • 根据上述思路,代码如下

代码

var minSwapsCouples = function (row) {
  const len = row.length
  const indexMap = {}
  for (let i = 0; i < len; i++) {
    const k = row[i]
    indexMap[k] = i
  }
  let result = 0
  for (let i = 0; i < len - 2; i += 2) {
    if ((row[i] ^ 1) === row[i + 1]) continue
    // 下一位置的值
    const next = row[i + 1]
    const nextIndx = indexMap[next]
    // 需要的值,需要的值位置在i+1处
    const should = row[i] ^ 1
    const shouldIdx = indexMap[should]
    row[nextIndx] = should
    row[shouldIdx] = next

    indexMap[next] = shouldIdx
    indexMap[should] = nextIndx
    // 交换map中数据

    result++
  }
  return result
}

并查集

  • 如果有情侣座错位置,那最少有2对情侣座错位置
  • 如果2对情侣座错位置,只需要交换1次即可
  • 如果3对情侣座错位置,只需要交换2次即可
  • ...
  • 如果n对情侣座错位置,只需要交换n-1次即可
  • 如何判断几对情侣座错位置?
  • 并查集
  • 并查集的关联关系是什么?
  • 寻找座错的情侣,如果情侣位置上对的,对任意位置x; 有row[x]>>2 === row[x+1]>>2
  • 如果情侣位置不对,row[x]>>2 !== row[x+1]>>2;
  • 座错位置的情侣会被合并到一个集合中
  • 统计集合中有多找坐对位置的情侣
  • 情侣对数量-做对位置的情侣数即可得到答案

以上思路并非我自己想到的,参考的宫水三叶大神的思路;

代码

var minSwapsCouples = function (row) {
  const len = row.length
  const list = Array(len / 2)
    .fill(0)
    .map((v, i) => i)
  for (let i = 0; i < len; i += 2) {
    const current = row[i] >> 1
    const next = row[i + 1] >> 1
    merge(current, next)
  }
  let ring = 0
  for (let i = 0; i < len / 2; i++) {
    if (i === find(i)) ring++
  }
  return len / 2 - ring

  function merge(x, y) {
    const rootX = find(x)
    const rootY = find(y)
    list[rootX] = rootY
  }

  function find(n) {
    if (list[n] === n) return list[n]
    const root = find(list[n])
    list[n] = root
    return root
  }
}

结语

我是软件开发工程师,不是月老;情侣不自己找相邻位置坐,为难我们写程序的干啥