【力扣】765. 情侣牵手
以下为力扣的官方题解
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
解释: 无需交换座位,所有的情侣都已经可以手牵手了。
说明
- len(row)len(row)len(row) 是偶数且数值在 [4,60][4, 60][4,60] 范围内。
- 可以保证 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(NlogN)O(N \log N)O(NlogN),其中 NNN 为情侣的总数。这里的并查集使用了路径压缩,但是没有使用按秩合并,最坏情况下的时间复杂度是 O(NlogN)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. 情侣牵手相关推荐
- 并查集-力扣-765. 情侣牵手
题目链接 n 对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手. 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位上的人的 ID.情侣们按顺序编号,第一对是 (0, ...
- 力扣765——情侣牵手(贪心+BFS)
解题思路 空间换时间 可以发现,每对情侣谁左谁右,旁边是谁,都没关系,只要这俩是一对且在一格就行: 因为要求全坐好,因为首尾不相连,下标0只能和下标1配对,这就相当于一格为两个偶奇下标: 首先遍历每一 ...
- 力扣.765情侣牵手——python
我们先了解一下题意求,只要情侣在左右都可以,而且求数字 x 的对象时用到了一个技巧,x 的对象是x ^ 1.解释如下: 当 x 是偶数,则其二进制的末尾是 0,所以 x ^ 1 将其二进制的末尾改成 ...
- LeetCode——765. 情侣牵手(Couples Holding Hands)——分析及代码(Java)
LeetCode--765. 情侣牵手[Couples Holding Hands]--分析及代码[Java] 一.题目 二.分析及代码 1. 并查集 (1)思路 (2)代码 (3)结果 三.其他 一 ...
- Leetcode 765. 情侣牵手 C++
Leetcode 765. 情侣牵手 题目 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交 ...
- Java实现 LeetCode 765 情侣牵手(并查集 || 暴力)
765. 情侣牵手 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交换座位. 人和座位用 0 ...
- 力扣题库-765.情侣牵手 最优解法
题目描述 情侣牵手 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交换座位. 人和座位用 0 ...
- LeetCode 765. 情侣牵手(贪心)
1. 题目 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交换座位. 人和座位用 0 到 2 ...
- Leetcode #765 情侣牵手(贪心算法)
目录 题目描述 解题思路 我的代码 心得 题目描述 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们 ...
最新文章
- 使用Linux进行缓冲区溢出实验的配置记录
- 配置Keil C51配置开发 STC51单片机过程
- git 修改全局配置
- 详解分布式一致性机制
- 比 Redis 快 5 倍的中间件,KeyDB
- 解决Maven管理项目update Maven时,jre自动变为1.5
- git submodule 子模块的管理和使用
- 第一个MapReduce程序-------WordCount
- oracle查看表空间和物理文件大小
- ar开发 ue4_UE4 和 ARKit 入门
- css中aspect,css 媒体查询 aspect-ratio less 使用方法
- Mvc5 EF6 CodeFirst Mysql (一) 新建一个Mvc项目并使用EF连接到Mysql数据库
- poj Matrix 回溯,递归,虽然对于很多人是水题,但我感觉这道题听好的嘛!!!!!!!!!!!
- 记第十七次CCF CSP认证
- vivado快速下载及解压安装教程
- DIY自平衡车意外失去左腿后,小哥爆改假肢玩出了花,稚晖君:技术到内心都硬核...
- Ubuntu中使用RoboMongo实现MongoDB的可视化
- Layui--入门指南
- 从新手到老鸟的脱变过程之《如何做手游项目》
- VC++获取病毒的消息钩子
热门文章
- PCB设计软件之Protel 99 SE和AD有铜孔及有铜槽做法
- 【渝粤教育】电大中专建筑材料_1作业 题库
- 计算机等级2级考试题库软件,XYZ计算机等级考试题库系统(二级Foxbase)
- 项目中沟通的几种方法对比
- 短信验证码60倒计时
- 使用Python、Pandas、Sklearn预测NBA比赛结果
- c语言游戏菜单栏界面设计,C语言课程设计-精美游戏目录选择界面.doc
- easypoi 实现任意格式的Excel导出(基于模板实现)
- WSL2+Docker环境搭建
- java随机抽题系统_JAVA程序设计题六:随机抽奖系统