2023-04-14:n对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手,
人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位上的人的ID,
情侣们按顺序编号,第一对是 (0, 1),第二对是 (2, 3),以此类推,最后一对是 (2n-2, 2n-1)。
返回 最少交换座位的次数,以便每对情侣可以并肩坐在一起。
每次交换可选择任意两人,让他们站起来交换座位。
输入: row = [0,2,1,3]。
输出: 1。
输入: row = [3,2,0,1]。
输出: 0。

答案2023-04-14:

大体过程如下:

  1. 定义并查集结构体 UnionFind,包括父节点数组 father、子树大小数组 size、辅助数组 help 和当前连通分量数 sets。

  2. 实现并查集结构体的三个方法:

    a. 初始化方法 new,初始化父节点数组和子树大小数组,并将父节点数组的值初始化为自身,连通分量数初始为节点数量。

    b. 查找方法 find,通过不断向上寻找父节点,直到找到根节点,并压缩路径优化查找效率。

    c. 合并方法 union,找到 i 和 j 所在的连通分量的代表元素 fi 和 fj,以子树大小来优化合并操作,并更新连通分量数。

  3. 实现计算最少交换座位次数的函数 min_swaps_couples,首先获取座位数量 n,然后初始化并查集 uf,遍历相邻的座位,将情侣所在的连通分量合并。最后返回需要交换座位的最小次数。

  4. 在 main 函数中分别调用 min_swaps_couples 函数,传入测试数据,并输出最少交换座位的次数。

  5. 根据测试数据 row = [0, 2, 1, 3],第一对情侣坐在座位0和1上,第二对情侣坐在座位2和3上,因此已经满足牵手的条件。而在测试数据 row = [3, 2, 0, 1] 中,第一对情侣坐在座位3和2上,第二对情侣坐在座位0和1上,因此需要交换他们的座位才能满足牵手的条件。

并查集的初始化时间复杂度为O(n),其中n为节点数量。在计算最少交换座位次数的函数 min_swaps_couples 中,遍历相邻的座位需要O(n) 的时间,每次调用并查集中的 find 方法和 union 方法的时间复杂度均为O(α(n)),其中α(n) 是阿克曼函数的反函数,它比对数函数增长得慢,可以近似看作常数级别。因此,总时间复杂度为O(nα(n))。

空间复杂度取决于节点数量,需要使用O(n) 的空间存储父节点数组、子树大小数组和辅助数组。

rust代码如下:

// 定义并查集结构体
struct UnionFind {
father: Vec<i32>, // 父节点数组
size: Vec<i32>, // 子树大小数组
help: Vec<i32>, // 辅助数组,用于优化路径压缩操作
sets: i32, // 当前连通分量数
} impl UnionFind {
// 初始化并查集
fn new(n: i32) -> Self {
let mut father = vec![0; n as usize]; // 初始化父节点数组
let size = vec![1; n as usize]; // 初始化子树大小数组
for i in 0..n {
father[i as usize] = i; // 父节点初始化为自身
}
UnionFind {
father, // 返回新建的并查集结构体
size,
help: vec![0; n as usize],
sets: n, // 初始时连通分量数为n
}
} // 查找i所在连通分量的代表元素
fn find(&mut self, mut i: i32) -> i32 {
let mut hi = 0;
while i != self.father[i as usize] {
// 不断向上寻找父节点,直到找到根节点
self.help[hi] = i; // 将当前节点压入辅助数组中
hi += 1;
i = self.father[i as usize]; // 向上跳一步
}
for j in (0..hi).rev() {
// 压缩路径
self.father[self.help[j] as usize] = i; // 将辅助数组中的节点的父节点设为根节点
}
i // 返回根节点
} // 合并i和j所在的连通分量
fn union(&mut self, i: i32, j: i32) {
let fi = self.find(i); // 找到i的代表元素
let fj = self.find(j); // 找到j的代表元素
if fi != fj {
// 如果i和j不在同一个连通分量中
if self.size[fi as usize] >= self.size[fj as usize] {
// 以树的大小来优化合并操作
self.father[fj as usize] = fi; // 将fj的父节点设为fi
self.size[fi as usize] += self.size[fj as usize]; // 更新fi子树的大小
} else {
self.father[fi as usize] = fj; // 将fi的父节点设为fj
self.size[fj as usize] += self.size[fi as usize]; // 更新fj子树的大小
}
self.sets -= 1; // 连通分量数减1
}
} // 获取当前连通分量数
fn sets(&self) -> i32 {
self.sets
}
} // 计算最少交换座位的次数
fn min_swaps_couples(row: Vec<i32>) -> i32 {
let n = row.len() as i32; // 座位数量
let mut uf = UnionFind::new(n / 2); // 初始化并查集
for i in (0..n).step_by(2) {
// 遍历相邻的座位
uf.union(row[i as usize] / 2, row[(i + 1) as usize] / 2); // 合并情侣所在的连通分量
}
n / 2 - uf.sets() // 返回需要交换座位的最小次数
} fn main() {
let row = vec![0, 2, 1, 3];
let swaps = min_swaps_couples(row);
println!("Minimum swaps required: {}", swaps); // Output: Minimum swaps required: 1 let row = vec![3, 2, 0, 1];
let swaps = min_swaps_couples(row);
println!("Minimum swaps required: {}", swaps); // Output: Minimum swaps required: 0
}

2023-04-14:n对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手, 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位上的人的ID, 情侣们按顺序编号,第一对的更多相关文章

  1. 有一个直方图,用一个整数数组表示,其中每列的宽度为1,求所给直方图包含的最大矩形面积。比如,对于直方图[2,7,9,4],它所包含的最大矩形的面积为14(即[7,9]包涵的7x2的矩形)。给定一个直方图A及它的总宽度n,请返回最大矩形面积。保证直方图宽度小于等于500。保证结果在int范围内。

    // ConsoleApplication5.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<vector> ...

  2. LeetCode 周赛 342(2023/04/23)容斥原理、计数排序、滑动窗口、子数组 GCB

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 前天刚举办 2023 年力扣杯个人 SOLO 赛,昨天周赛就出了一场 Easy - Ea ...

  3. CVE-2015-1328 Ubuntu 12.04, 14.04, 14.10, 15.04 overlayfs Local Root

    catalog . 引言 . Description . Effected Scope . Exploit Analysis . Principle Of Vulnerability . Patch ...

  4. 如何教你在NIPS会议上批量下载历年的pdf文档(另附04~14年NIPS论文下载链接)

    如何获得NIPS会议上批量下载的链接? NIPS会议下载网址:http://papers.nips.cc/ a.点击打开上述网站,进入某一年的所有会议,例如2014年,如下图 b.然后对着当前网页点击 ...

  5. Ubuntu LTS 系统学习使用体会和实用工具软件汇总 6.04 8.04 10.04 12.04 14.04 16.04

    Ubuntu LTS 系统学习体会和工具软件汇总 6.04 8.04 10.04 12.04 14.04 16.04 ubuntu入门必备pdf:http://download.csdn.net/de ...

  6. 14.9 InnoDB Row Storage and Row Formats InnoDB 行存储和行格式:

    14.9 InnoDB Row Storage and Row Formats InnoDB 行存储和行格式: 14.9.1 Overview of InnoDB Row Storage 14.9.2 ...

  7. Ubuntu 14.04/14.10下安装VMware Workstation 11图文教程

    VMware workstation 是一个可以进行桌面操作的虚拟软件.它可以让我们在一台电脑或者虚拟机中运行多个虚拟机. 由VMware公司研发和维护.由于是商业软件,我们需要买他们家的许可证或者说 ...

  8. [转] Ubuntu 14.04/14.10下安装VMware Workstation 11图文教程

    点击这里查看原文 译者:GuiltyMan 本文由 Linux公社翻译组 原创翻译  Linux公社 诚意奉献 更多请访问此处博客网站 VMware workstation 是一个可以进行桌面操作的虚 ...

  9. 安装ubuntu出现BUG soft lockup的解决方法(16.04 14.04)

    对于16.04而言,当时用的是UtrISO 安装的,导致安装过程用会出现 “not a com32r image” 的错误,解决方法见上文的: boot: live 华硕Z9主板安装16.04以上系统 ...

  10. 每日一练ACM 2019.04.14

    2019.4.14 第1001题:Sum Problem Problem DescriptionHey, welcome to HDOJ(Hangzhou Dianzi University Onli ...

随机推荐

  1. spring-boot-starter-webflux

    webflux: 反应式编程reactor的产物,采用发布订阅模式,引入netty的nio,比较适合IO密集型应用. 因普遍应用使用的DB链接是IO阻塞型,因此在一般应用中无法体现它的优势.redis ...

  2. 图像主题颜色提取(Median cut)

    前言 之前想对图片素材进行分类管理,除了打标签,还有一样是通过主题色进行分类.于是开始寻找能提取主主题色的工具,最后找到了大名鼎鼎的 Leptonica 库,其中就有中位切割算法的实现.下面附上中位切 ...

  3. 密码破解-hashcat的简单使用

    在我们抓取到系统的hash值之后,需要通过一些工具来破解密码 hashcat是一款可以基于显卡暴力破解密码的工具,几乎支持了所有常见的加密,并且支持各种姿势的密码搭配 在kali Linux中自带的有 ...

  4. Python学习笔记--异常+模块+包

    异常的捕获 基本语法: 示例: 捕获指定异常 基本语法:--必写 示例: 捕获多个异常 示例: 捕获所有异常 示例: 异常else--可写可不写 示例: 异常finally(无论是否出现异常,都会去执 ...

  5. MySQL学习(六)timestamp & datetime 区别

    参考博客: https://cloud.tencent.com/developer/article/1407693 timestamp只使用datetime一半的存储空间,并且会根据时区变化,具有特殊 ...

  6. 机器学习(二):感知机+svm习题 感知机手工推导参数更新 svm手推求解二维坐标超平面直线方程

    作业1: 输入: 训练数据集 \(T = {(x1; y1); (x2; y2),..., (xN; yN)}\) 其中,\(x \in R^n\), \(y \in Y = \{+1, -1\}\) ...

  7. 跳出思维的“盒子”,聊聊 RTE 应用创新大赛的那些作品

    由声网Agora 与环信联合主办的"RTE 2021 编程挑战赛"已圆满落幕.在今年的大赛中,来自行业中不同领域的专家参与了决赛评选,包括 Linux 中国技术社区技术负责人 白宦 ...

  8. vulnhub靶场之BLUESMOKE: DEVRANDOM2|bluesmoke

    准备: 攻击机:虚拟机kali.本机win10. 靶机:Bluesmoke: devrandom2,下载地址:https://download.vulnhub.com/bluesmoke/Bluesm ...

  9. springboot 连接不上 redis 的三种解决方案!

    针对于这种情况,首先,我们最简单直接的方法就是需要确认Redis是否已经正常启动(验证方法:如果安装在Linux下的话可以使用ps-ef|grep redis来进行确认是否开启) 如果未开启,我们可以 ...

  10. KMP算法的研究

    前脚学后脚忘,是时候给自己通俗易懂的总结一下了 KMP是什么 在计算机科学中,Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个字符串S内查找一个词W的出现位置.一个词在不 ...