并查集详解及模板

1. 解决什么问题?

当题目最终要将数据分成若干个集合时,可往并查集的方向思考。并查集三个字拆开对应“合并”,“查找”,“集合”,这样就很好理解了。

【思路】

为了方便查找和合并,每个元素都有对应的代表元素,代表元素就是它所在集合里的所有元素的代表元素。

因此,要构建一个 father 数组 表示每个元素的代表元素。

2. 模板

1)构建集合/初始化

一开始每个元素就是自己的代表元素,后续根据题目要求进行合并,如果要求集合的个数也可以在此处表示。

也不一定写成函数,此处只是为了方便展示。

void build(int n)
{for (int i = 1; i < n; i++)father[i] = i;sets = n;
}

2)查找:递归思路

如果 i == father[i] ,则 i 为代表元素。

而当一个元素的 father 不是本身时,则再找 father 的 father,知道找到代表元素为止。

int find(int p)
{if (father[p] != p){father[p] = find(father[p]);}return father[p];
}

3)合并

将代表元素合并,也就是相当于两个集合合成一个集合

 void set_union(int x, int y){int fx = find(x);int fy = find(y);if (fx != fy){father[fx] = fy;sets--;}}

3. 优化

一般的并查集用上面的模板就可以,如果想更快些,可以看下面的版本,但需要的空间会大些

1)扁平化

【思路】

因为 find 方法调用频繁,所以如果将递归的次数减少一些会大大优化时间复杂度

优化方法就是将同一代表元素的元素的 father 都改成代表元素(原先是通过递归来实现的)

【实现方式】

需要开一个栈来实现:栈来收集从该元素到代表元素沿途的元素,再将他们的 father 一一改成代表元素

而当下次再调用时,就可以只循环一次,找到它的 father。

int find(int i) {int size = 0;while (i != father[i]) {stack[size++] = i;i = father[i];}while (size > 0) {father[stack[--size]] = i;}return i;
}

2)小挂大

需要多开一个数组表示代表元素对应的集合的元素个数,记为 size 数组,初始化时全为1

两个集合合并表示为对应代表元素的 size 值小的加到大的上

void set_union(int × int y) 
{int fx = find(x);int fy = find(y);if (fx != fy) {// 小的挂在大的上if (size[f×] >= size[fy]) {size[f×] += size[fy];father[fy] = fx;} else {size[fy] += size[f×];father[fx] = fy;}}
}

PS:如果看模板不好理解,最好结合练习看会舒服很多

4. 练习

(1)模板题

链接:牛客_并查集的实现

(2)相似字符串组

链接:leet_839

【分析】

核心思路就是并查集,通过记录每个字符串的不同字符数找相似字符串,然后按并查集的思路合并,最终输出集合的个数。

【参考代码】链接

(3)情侣牵手

链接:leet_765

【分析】

情侣数一定是人数的一半,故只需开人数一半的集合即可,规定其 ID 对应除以2的数就是对应的情侣 ID;

那么每一次相邻两个元素合并就将其情侣 ID (可理解为代表元素)合并即可,因为在合并的函数中,属于相同集合的不用再进行操作,而只有不是属于一个集合的才减少集合的个数

【参考代码】链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/686098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Qt笔记】QSS中常用的子控件

QSS中常用的子控件 子控件名称说明::branchQTreeView的分支指示器::chunkQProgressBar的进度显示块::close-buttonQDockWidgte或QTabBar页面的关闭按钮::down-arrowQComboBox、QHeaderView(排序指示器)、QScrollBar或QSpinBox的下拉箭头::down-buttonQScrollBar或QSpinBox的向…

C语言——oj刷题——杨氏矩阵

目录 1. 理解杨氏矩形的特点 2. 实现杨氏矩形查找算法 3. 编写示例代码 当我们谈到杨氏矩形时&#xff0c;我们指的是一种在二维数组中查找目标元素的高效算法。它是由杨氏&#xff08;Yan Shi&#xff09;教授提出的&#xff0c;因此得名为杨氏矩形。 杨氏矩形问题的场景是…

必考板子题【Py/Java/C++三种语言详解】LeetCode每日一题240214【二叉树BFS】LeetCode102、二叉树的层序遍历

有LeetCode交流群/华为OD考试扣扣交流群可加&#xff1a;948025485 可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题 绿色聊天软件戳 od1336了解算法冲刺训练 文章目录 题目链接题目描述解题思路DFS和BFS异同用队列维护的BFS 代码PythonPythonJavaC时空复杂度 相关习题华为OD算…

初始Git及Linux Centos下安装Git

文章目录 前言版本控制器注意Git安装 前言 不知道你⼯作或学习时&#xff0c;有没有遇到这样的情况&#xff1a;我们在编写各种⽂档时&#xff0c;为了防⽌⽂档丢失&#xff0c;更改失误&#xff0c;失误后能恢复到原来的版本&#xff0c;不得不复制出⼀个副本&#xff0c;⽐如…

一个小白的转行Python的经历!

1. 寻找一个导师 导师可以降低你加入一个新行业的成本&#xff0c;帮助你熟悉环境和行业规则&#xff0c;也会鼓励你完成心理方面的转变。 2. 建立新的社交网络 过去的人脉关系会阻碍你的转行&#xff0c;因为他们是以过去对你的认知来评价你。新领域的人脉&#xff0c;会给你提…

牛客2024年除夕娱乐赛

纯娱乐&#xff0c;就第四题值得一看。 A 我有一款游戏 code&#xff1a; #include <iostream> #include <cstdio> using namespace std;int main(){cout<<"原神启动";return 0; } B 除夜 #include <iostream> #include <cstdio> u…

互联网时代的文学复兴:中文诗词大数据分析 | 开源日报 No.170

chinese-poetry/chinese-poetry Stars: 45.4k License: MIT 最全的中文诗歌古典文集数据库&#xff0c;包含 5.5 万首唐诗、26 万首宋诗、2.1 万首宋词和其他古典文集。数据来源于互联网。该开源项目旨在通过 JSON 格式分发&#xff0c;方便用户开始自己的项目&#xff0c;并借…

Error: Illegal arguments: undefined string at bcrypt.hashSync

用react写后端的signUp时出现报错undefined string at bcrypt.hashSync&#xff0c;代码如下&#xff0c;报错在生成password时&#xff01; const bcrypt require(bcryptjs) const jwt require(jsonwebtoken) const db require(../config/db.config.js) const User db.us…

文件夹删不掉,显示在另一个文件中打开怎么办

问题&#xff1a; 一、想要删掉这个文件夹&#xff0c;却因为文件夹中的文件打开了删不掉&#xff0c;这里我因为做的测试&#xff0c;所以是知道打开了什么 二、一般情况下文件比较多时&#xff0c;是不知道打开了什么的&#xff0c;长这个样子 解决&#xff1a; 一、打开任…

嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第五天-ARM Linux编程之字符设备驱动(物联技术666)

链接&#xff1a;https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd1688 提取码&#xff1a;1688 教学内容&#xff1a; 1、内核模块的简单框架&#xff1a; __init __exit执行完后就释放空间 简单框架&#xff1a;包含三个部分 1&#xff09;模块初始化和模块退出函数…

Python算法题集_将有序数组转换为二叉搜索树

Python算法题集_将有序数组转换为二叉搜索树 题108&#xff1a;将有序数组转换为二叉搜索树1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【极简代码递归】2) 改进版一【多行代码递归】3) 改进版二【极简代码递归传递下标】 4. 最优算法 本文为…

备战蓝桥杯---图论之最小生成树

首先&#xff0c;什么是最小生成树&#xff1f; 他就是无向图G中的所有生成树中树枝权值总和最小的。 如何求&#xff1f; 我们不妨采用以下的贪心策略&#xff1a; Prim算法&#xff08;复杂度&#xff1a;&#xff08;nm)logm)&#xff1a; 我们对于把上述的点看成两个集…

NX二次开发树列表双击快速进入编辑状态

先将这几个树列表回调注释给解开 int TreeColumn0;//定义一个全局边量记录点击的那一列NXOpen::BlockStyler::Tree::BeginLabelEditState OnBeginLabelEditCallback(NXOpen::BlockStyler::Tree *tree,NXOpen::BlockStyler::Node *node,int columID) {if(columnIDTreeColumnID)…

无人机基本知识,无人机遥控器功能详解与调试方法

无人机作为一种新兴的飞行器&#xff0c;近年来在各个领域得到了广泛的应用。而无人机遥控器则是控制无人机飞行的重要工具。 无人机遥控器是一种无线设备&#xff0c;通过它来远程控制无人机的飞行。遥控器通常包括一个或多个摇杆&#xff0c;用于控制无人机的各种动作&#x…

QGIS004:【10栅格地形分析工具箱】-坡度、坡向、山体阴影

摘要&#xff1a;QGIS栅格地形分析工具箱常用工具有坡度、坡向、山体阴影等选项&#xff0c;本文介绍各选项的基本操作。 实验数据&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1gYZ_om4AlSdal0bts2mt-A?pwd4rrn 提取码&#xff1a;4rrn 一、坡度 工具功能&…

【计算机网络】概述和运输层服务

运输层协议是在端系统中而不是在路由器中实现报文段 segment 运输层将从发送应用程序进程接收到的报文转化成运输层分组 将应用层报文划分为较小的块&#xff0c;并为每一块加上一个运输层首部运输层将报文段传递给网络层&#xff0c;网络层将其封装成网络层分组&#xff08;…

B端系统从0到1:有几步,其中需求分析要做啥?

一款B系统从无到有都经历了啥&#xff0c;而其中的需求分析又要做什么&#xff1f;贝格前端工场给老铁们做一下分析&#xff0c;文章写作不易&#xff0c;如果咱们有界面设计和前端开发需求&#xff0c;别忘了私信我呦&#xff0c;开始了。 一、B端系统从0到1都有哪些要走的步骤…

Vue练习3:组件开发3(页面切换)

预览 ——————————————————————————————————————————— 组件文档 Pager组件 属性 属性名含义类型必填默认值current当前页码&#xff08;总数据量/单页容量&#xff09;Number否1total总数据量Number否0limit单页容量Number否10vis…

Day-02-01

内容管理模块项目开发 Swagger的使用 1. 导入依赖 <!-- Spring Boot 集成 swagger --> <dependency><groupId>com.spring4all</groupId><artifactId>swagger-spring-boot-starter</artifactId> </dependency> 2. 配置信息 # 在app…

为何重复造轮子

重复造轮子&#xff0c;意思是说&#xff0c;一个项目本身存在开源组件&#xff0c;但开发团队还是选择重新手写一套组件库或框架的情况&#xff0c;这在软件业界比比皆是。 下面说下游戏项目里重复造轮子的几点原因。 一&#xff0c;精简化 一般开源项目为了适应多场景多业…