以下为力扣的官方题解

765. 情侣牵手

  • 题目
  • 示例1
  • 示例2
  • 说明
  • 官方题解
    • 思路一 并查集
      • 代码
      • 复杂度分析
    • 思路二 广度优先搜索
      • 代码
      • 复杂度分析

题目

NNN 对情侣坐在连续排列的 2N2N2N 个座位上,想要牵到对方的手。 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起。 一次交换可选择任意两人,让他们站起来交换座位。
人和座位用 000 到 2N−12N-12N−1 的整数表示,情侣们按顺序编号,第一对是 (0,1)(0, 1)(0,1),第二对是 (2,3)(2, 3)(2,3),以此类推,最后一对是 (2N−2,2N−1)(2N-2, 2N-1)(2N−2,2N−1)。
这些情侣的初始座位 row[i]row[i]row[i] 是由最初始坐在第 iii 个座位上的人决定的。

示例1

输入: row=[0,2,1,3]row = [0, 2, 1, 3]row=[0,2,1,3]
输出: 111
解释: 我们只需要交换 row[1]row[1]row[1] 和 row[2]row[2]row[2] 的位置即可。

示例2

输入: row=[3,2,0,1]row = [3, 2, 0, 1]row=[3,2,0,1]
输出: 000
解释: 无需交换座位,所有的情侣都已经可以手牵手了。

说明

  1. len(row)len(row)len(row) 是偶数且数值在 [4,60][4, 60][4,60] 范围内。
  2. 可以保证 rowrowrow 是序列 0...len(row)−10...len(row)-10...len(row)−1 的一个全排列。

官方题解

思路一 并查集

假定第一对情侣的男生与第二对情侣的女生坐在了一起,而第二对情侣的男生与第三对情侣的女生坐在了一起。根据题意,要想让第二对情侣之间能够成功牵手,要么交换第一对情侣的男生与第二对情侣的男生,要么交换第二对情侣的女生与第三对情侣的女生。

既然存在这两种交换方式,那么有必要两种方式都考虑吗?答案是无需都考虑。不难注意到,无论采用了两种交换方式中的哪一种,最后的结局都是「第二对情侣坐在了一起,且第一对情侣的男生与第三对情侣的女生坐在了一起」,因此两种交换方式是等价的。

因此,我们将 NNN 对情侣看做图中的 NNN 个节点;对于每对相邻的位置,如果是第 iii 对与第 jjj 对坐在了一起,则在 iii 号节点与 jjj 号节点之间连接一条边,代表需要交换这两对情侣的位置。

如果图中形成了一个大小为 kkk 的环:i→j→k→…→l→ii \rightarrow j \rightarrow k \rightarrow \ldots \rightarrow l \rightarrow ii→j→k→…→l→i,则我们沿着环的方向,先交换 i,ji,ji,j 的位置,再交换 j,kj,kj,k 的位置,以此类推。在进行了 k−1k-1k−1 次交换后,这 kkk 对情侣就都能够彼此牵手了。

故我们只需要利用并查集求出图中的每个连通分量;对于每个连通分量而言,其大小减 111 就是需要交换的次数。

代码

class Solution {public int minSwapsCouples(int[] row) {int n = row.length;int tot = n/2;int[] f = new int[tot];for (int i=0; i<tot; i++){f[i] = i;}for (int i=0; i<n; i+=2){int l = row[i]/2;int r = row[i+1]/2;add(f, l, r);}Map<Integer, Integer> map = new HashMap<Integer, Integer>();for (int i=0; i<tot; i++){int fx = getf(f, i);map.put(fx, map.getOrDefault(fx, 0)+1);}int ret = 0;for (Map.Entry<Integer, Integer> entry : map.entrySet()){ret += entry.getValue()-1;}return ret;}public int getf(int[] f, int x) {if (f[x] == x){return x;}int newf = getf(f, f[x]);f[x] = newf;return newf;}public void add(int[] f, int x, int y) {int fx = getf(f, x);int fy = getf(f, y);f[f[x]] = fy;}
}

复杂度分析

  • 时间复杂度:O(Nlog⁡N)O(N \log N)O(NlogN),其中 NNN 为情侣的总数。这里的并查集使用了路径压缩,但是没有使用按秩合并,最坏情况下的时间复杂度是 O(Nlog⁡N)O(N \log N)O(NlogN),平均情况下的时间复杂度依然是 O(Nα(N))O(N \alpha (N))O(Nα(N)),其中 α\alphaα 为阿克曼函数的反函数,α(N)\alpha (N)α(N) 可以认为是一个很小的常数。
  • 空间复杂度:O(N)O(N)O(N)。

思路二 广度优先搜索

我们也可以通过广度优先搜索的方式,求解图中的连通分量。

起初,我们将每个节点都标记为「未访问」,并遍历图中的每个节点。如果发现一个「未访问」的节点,就从该节点出发,沿着图中的边,将其余的「未访问」的节点都标记为「已访问」,并同时统计标记的次数。当遍历过程终止时,标记的数量次数即为连通分量的大小。

代码

class Solution {public int minSwapsCouples(int[] row) {int n = row.length;int tot = n/2;List<Integer>[] graph = new List[tot];for (int i=0; i<tot; i++){graph[i] = new ArrayList<Integer>();}for (int i=0; i<n; i+=2){int l = row[i]/2;int r = row[i+1]/2;if (l != r){graph[l].add(r);graph[r].add(l);}}boolean[] visited = new boolean[tot];int ret = 0;for (int i=0; i<tot; i++){if (!visited[i]){Queue<Integer> queue = new LinkedList<Integer>();visited[i] = true;queue.offer(i);int cnt = 0;while (!queue.isEmpty()){int x = queue.poll();cnt ++;for (int y : graph[x]){if (!visited[y]){visited[y] = true;queue.offer(y);}}}ret += cnt-1;}}return ret;}
}

复杂度分析

  • 时间复杂度:O(N)O(N)O(N),其中 NNN 为情侣的总数。每个节点最多只被标记 111 次。
  • 空间复杂度:O(N)O(N)O(N),其中 NNN 为情侣的总数。为队列的开销。

【力扣】765. 情侣牵手相关推荐

  1. 并查集-力扣-765. 情侣牵手

    题目链接 n 对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手. 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位上的人的 ID.情侣们按顺序编号,第一对是 (0, ...

  2. 力扣765——情侣牵手(贪心+BFS)

    解题思路 空间换时间 可以发现,每对情侣谁左谁右,旁边是谁,都没关系,只要这俩是一对且在一格就行: 因为要求全坐好,因为首尾不相连,下标0只能和下标1配对,这就相当于一格为两个偶奇下标: 首先遍历每一 ...

  3. 力扣.765情侣牵手——python

    我们先了解一下题意求,只要情侣在左右都可以,而且求数字 x 的对象时用到了一个技巧,x 的对象是x ^ 1.解释如下: 当 x 是偶数,则其二进制的末尾是 0,所以 x ^ 1 将其二进制的末尾改成 ...

  4. LeetCode——765. 情侣牵手(Couples Holding Hands)——分析及代码(Java)

    LeetCode--765. 情侣牵手[Couples Holding Hands]--分析及代码[Java] 一.题目 二.分析及代码 1. 并查集 (1)思路 (2)代码 (3)结果 三.其他 一 ...

  5. Leetcode 765. 情侣牵手 C++

    Leetcode 765. 情侣牵手 题目 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交 ...

  6. Java实现 LeetCode 765 情侣牵手(并查集 || 暴力)

    765. 情侣牵手 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交换座位. 人和座位用 0 ...

  7. 力扣题库-765.情侣牵手 最优解法

    题目描述 情侣牵手 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交换座位. 人和座位用 0 ...

  8. LeetCode 765. 情侣牵手(贪心)

    1. 题目 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交换座位. 人和座位用 0 到 2 ...

  9. Leetcode #765 情侣牵手(贪心算法)

    目录 题目描述 解题思路 我的代码 心得 题目描述 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们 ...

最新文章

  1. 使用Linux进行缓冲区溢出实验的配置记录
  2. 配置Keil C51配置开发 STC51单片机过程
  3. git 修改全局配置
  4. 详解分布式一致性机制
  5. 比 Redis 快 5 倍的中间件,KeyDB
  6. 解决Maven管理项目update Maven时,jre自动变为1.5
  7. git submodule 子模块的管理和使用
  8. 第一个MapReduce程序-------WordCount
  9. oracle查看表空间和物理文件大小
  10. ar开发 ue4_UE4 和 ARKit 入门
  11. css中aspect,css 媒体查询 aspect-ratio less 使用方法
  12. Mvc5 EF6 CodeFirst Mysql (一) 新建一个Mvc项目并使用EF连接到Mysql数据库
  13. poj Matrix 回溯,递归,虽然对于很多人是水题,但我感觉这道题听好的嘛!!!!!!!!!!!
  14. 记第十七次CCF CSP认证
  15. vivado快速下载及解压安装教程
  16. DIY自平衡车意外失去左腿后,小哥爆改假肢玩出了花,稚晖君:技术到内心都硬核...
  17. Ubuntu中使用RoboMongo实现MongoDB的可视化
  18. Layui--入门指南
  19. 从新手到老鸟的脱变过程之《如何做手游项目》
  20. VC++获取病毒的消息钩子

热门文章

  1. PCB设计软件之Protel 99 SE和AD有铜孔及有铜槽做法
  2. 【渝粤教育】电大中专建筑材料_1作业 题库
  3. 计算机等级2级考试题库软件,XYZ计算机等级考试题库系统(二级Foxbase)
  4. 项目中沟通的几种方法对比
  5. 短信验证码60倒计时
  6. 使用Python、Pandas、Sklearn预测NBA比赛结果
  7. c语言游戏菜单栏界面设计,C语言课程设计-精美游戏目录选择界面.doc
  8. easypoi 实现任意格式的Excel导出(基于模板实现)
  9. WSL2+Docker环境搭建
  10. java随机抽题系统_JAVA程序设计题六:随机抽奖系统