并查集,真好用,一次AC不是梦!

news2024/11/26 23:47:06

请添加图片描述

文章目录

  • 🚀前言
  • 🚀并查集
  • 🚀并查集的两个优化
    • ✈️路径压缩
    • ✈️按秩合并
  • 🚀并查集代码模板

🚀前言

大家好啊!今天阿辉来给大家介绍一种简洁而优雅的数据结构——并查集,不知道各位是否了解它,如果你在题解区见到并查集,想必各位一定见过类似下面这样的评论
在这里插入图片描述
在这里插入图片描述
好了,阿辉也不卖关子了,开始咱们今天的学习吧!!!!

🚀并查集

并查集是一种树形数据结构,每一棵树代表一个集合,支持两种操作:

  • isSameSet方法:查找两个元素是否为同一集合
  • uinionSet方法:合并两个集合

并查集与二叉树这类树形结构并不相同,二叉树的每个节点都维护着他的两个子节点,而并查集则是每个节点都指向其父节点直至根节点,而根节点指向自己,类似于下图这样的结构
请添加图片描述

根节点15指向自己,他们的子节点指向其父节点,一棵树代表一个集合,对于每一棵树它的根节点又被称为代表节点,因为集合中的任意节点都能找到其根节点,判断两元素是否在同一集合就是判断量元素的根节点(代表节点)是否相同,这也就是isSameSet方法

15两个集合如何合并呢?
这很简单只需要其中一棵树的代表节点指向另一棵树的代表节点即可,如下图:
请添加图片描述
很明显,isSameSetunionSet方法都需要一个find方法来找到元素的代表节点从而实现合并和查询功能,find方法的实现也是很容易,拿到一个节点一直往上找当自己就是父节点时,就找到代表节点了。
但并查集的厉害还未展现
并查集的厉害之处在于,它的isSameSetunionSet方法的单次操作的均摊时间复杂度可以达到接近 O ( 1 ) O(1) O(1),也就是说在通常情况下对于并查集的单次操作我们认为是常数时间

各位是不觉得我在开玩笑,因为很明显集合元素的增长会使得树的高度不断扩大,会导致find方法的效率变差,没错是这样的,不过并查集的两个优化会使得find方法异常高效近乎就是常数时间

🚀并查集的两个优化

✈️路径压缩

并查集的第一个优化就是路径压缩,实际操作呢也很简单,上图
请添加图片描述
也就是上面这样高度为4的树在经历一次find后,虽然这一次遍历了4个节点但是下一次find操作剩下的节点只需要常数时间就能找到代表节点,即便一个高度为n的数如果从底部find一次,今后剩下的节点都直接指向代表节点,他们进行find操作都是常数时间,每次find操作近乎 O ( 1 ) O(1) O(1)的时间复杂度,好吧,很遗憾阿辉不会证明,但是上面的解释相信大家能感受到并查集确实能很快
其实在各类算法竞赛中往往并查集只用到路径压缩这一种优化,就可以认为并查集的各种操作时间复杂度为 O ( 1 ) O(1) O(1)

并查集于1964年发表,于1989年才证明其时间复杂度近乎常数时间

并查集的证明很难,各位有兴趣可以研究🧐

✈️按秩合并

相信各位看到这个按秩合并很懵,没关系我一开始懵

“按秩合并”是一种优化并查集性能的技术。在这里,“秩”可以理解为树的“高度”或“深度”,代表集合的某种“大小”指标。按秩合并的基本思想是总是将较小的树连接到较大的树上,这样可以避免树变得过高,从而减少查找时的路径长度

很官方的话,总感觉不像人说的,其实秩就可以理解为,一个集合中的元素个数,当两个集合合并时,元素个数少的要挂在元素多的集合下,一般情况下元素多的集合的这棵树也相对较高,为了尽量降低树的高度,所以要按秩合并(不如小挂大是吧!)

🚀并查集代码模板

以数组实现并查集,最经典的用法,附上牛客并查集模板测试链接

//MAXN根据题目的数据量进行更改
#define MAXN 101
//用father数组实现每个元素的父节点,比如题目数据量是100,就开101大小的空间
//数组下表与数组元素属于天然的<int,int>的映射表
int father[MAXN];
//size数组里面存着每个集合的元素个数,由代表节点映射
int size[MAXN];
//build方法相当于对并查集初始化
void build(int n){
    for(int i = 0;i < n;++i){
        father[i] = i;//一开始每个元素的父节点是自己
        size[i] = 1;//每个集合都只有一个元素
    }
}
//find方法,找集合的代表节点
//一个三目运算很优雅,懒人专用
//int find(int x){
    //return father[x] = x != father[x] ? find(father[x]) : x;
//}
int find(int x){
	if(x != father[x]){//如果父节点不是自己就调递归
	//找到代表节点后返回到上一级递归时,先把当前节点的父节点直接改成代表节点
		father[x] = find(father[x]);
	}
	return father[x];//然后返回当前节点的父节点父节点
}
bool isSameSet(int x,int y){
    return find(x) == find(y);//代表节点相同则在同一集合,否则不在
}
void unionSet(int x,int y){
    int fx = find(x);//x所在集合代表节点
    int fy = find(y);//y所在集合代表节点
    //小挂大
    if(size[fx] < size[fy]){
        father[fx] = fy;
        size[fy] += size[fx];//同时更新新集合元素个数
    }else{
        father[fy] = fx;
        size[fx] += size[fy];//同时更新新集合元素个数
    }
}

一般在刷题的过程中,并查集的使用往往只需要路径压缩这一优化即可,更简洁并查集模板附上洛谷并查集模板测试链接

#define MAXN 100
int find[MAXN];
void build(int n){
    for(int i = 0;i < n;++i){
        father[i] = i;
    }
}
int find(int x){
    return father[x] = father[x] != x ? find(father[x]) : x;
}
bool isSameSet(int x,int y){
    return find(x) == find(y);
}
void unionSet(int x,int y){
    father[find(x)] = find(y);//没有小挂大了,谁挂谁无所谓
}

虽然很少用到小挂大,但是size并不是用不到,并查集可以给每个集合加上标签,就像size表示大小,还可以根据需要给不同的集合加上标签


请添加图片描述

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

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

相关文章

IC会员卡写编号,写印刷卡号,卡面卡号,加密D3读卡器R330读卡器会员卡系统

IC卡作为会员卡来使用&#xff0c;比磁条卡安全耐用 游戏厅会员卡、酒店会员卡、美容养生会所会员卡等 IC卡片印刷好以后&#xff0c;要把卡面印刷编号写入到卡片中&#xff0c;才可以在会员卡系统上使用 用以下软件可以批量写入 写入以后&#xff0c;我读取卡片内的数据 把数…

旧衣回收小程序开发,市场发展潜力巨大

在当下快节奏生活下&#xff0c;人们的闲置衣物越来越多&#xff0c;为了减少浪费&#xff0c;旧衣回收成成为了大众的选择。旧衣回收能够降低人们的损失&#xff0c;减少我国资源浪费&#xff0c;又能循环利用&#xff0c;是我国一个环保商业模式。 “互联网旧衣回收”推动市场…

【Effective Objective - C】—— block 块

【Effective Objective - C】—— block 块 前言37.理解块的概念块的基础知识块可以捕获变量内联块的用法块的内部结构栈块堆块全局块要点 38.为常用的块类型创建typedef要点 39.用handler块降低代码分散程度协议传值实现异步块实现异步回调操作里的块要点 40.用块引用其所属对…

JAVA高并发——JDK的并发容器

文章目录 1、超好用的工具类&#xff1a;并发集合简介2、线程安全的HashMap3、深入浅出ConcurrentHashMap3.1、ConcurrentHashMap的内部数据结构3.2、put()方法的实现3.3、get()方法的实现 4、有关List的线程安全5、高效读写的队列&#xff1a;深度剖析ConcurrentLinkedQueue类…

USB隔离模块(ADUM4160)--- 保护您的创新:从高精度到高电压

所需设备&#xff1a; 1、ISOUSB 隔离器&#xff1b; 数据信号、电源 双重隔离&#xff1b; ISOUSB 隔离器采用实现单个 USB 输入&#xff0c;单个USB 隔离输出功能&#xff0c;方便实际应用。另外&#xff0c;本产品采用 ADI 公司的 iCoupler 磁耦隔离技术&#xff0c;芯片…

震惊世界的Sora发明者之一,是毕业于上海交大的天才少年-谢赛宁?(本人辟谣)

很少发票圈&#xff0c;如果大家看到这个公众号标题党的离大谱的文章&#xff0c;求一定帮忙点下举报不实信息。如果有认识微信相关部门的朋友也请联系我一下。 Sora是bill他们在openai的呕心之作&#xff0c;我虽然不知道细节&#xff0c;但是bill告诉我他们每天基本不睡觉高强…

多线程——

目录 一、为什么要有多线程&#xff1f; 1、线程与进程 2、多线程的应用场景 3、小结​编辑 二、多线程中的两个概念&#xff08;并发和并行&#xff09; 1、并发 2、并行 3、小结 三、多线程的三种实现方式 1、继承Thread类的方式进行实现 2、实现Runnable接口的方…

【每日一题】三数之和

三数之和&#xff0c;点击左侧即可跳转。 目录 题目详情&#xff1a;思路&#xff1a;暴力&#xff1a;双指针&#xff1a; 代码实现&#xff1a; 题目详情&#xff1a; 思路&#xff1a; 暴力&#xff1a; 我们会显而易见的想到使用暴力解法&#xff0c;3个for循环暴力枚举…

如何在Ubuntu系统使用Docker部署开源白板工具Excalidraw并实现公网访问

文章目录 1. 安装Docker2. 使用Docker拉取Excalidraw镜像3. 创建并启动Excalidraw容器4. 本地连接测试5. 公网远程访问本地Excalidraw5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 本文主要介绍如何在Ubuntu系统使用Docker部署开源白板工具Excal…

JavaAgent介绍 | 基本介绍及无侵入打印方法耗时

闲聊 最近在配置skywalking的过程中发现了-javaagent:这个配置&#xff0c;这里做一个简单的学习 什么是JavaAgent 网上似乎没有直接的文档介绍这个&#xff0c;只找了instrument包的相关文档&#xff0c;其内容页。其中的内容也都是介绍javaagent相关。 instrument包下核心…

【深蓝学院】移动机器人运动规划--第5章 最优轨迹生成--笔记

文章目录 1. Preliminaries2. Multicopter dynamics and differential flatness&#xff08;多旋翼动力学和微分平坦特性&#xff09;2.1 Differential Flatness2.2 具体建模2.3 Flatness Transformation的解析推导 3. Trajectory Optimization轨迹优化3.1 Problem formulation…

5年测试被裁,年前恶补3个月上岸字节28K,面试差点被问哭···

我的个人背景非常简单&#xff0c;也可以说丝毫没有亮点。 学历普通&#xff0c;计算机专业二本毕业&#xff0c;毕业后出来就一直在一家小公司&#xff0c;岁月如梭细&#xff0c;算了下至今从事软件测试已经5年了&#xff0c;也点点点了五年&#xff0c;每天都是重复的工作&…

【 JS 进阶 】原型对象、面向对象

目标 了解构造函数原型对象的语法特征&#xff0c;掌握 JavaScript 中面向对象编程的实现方式&#xff0c;基于面向对象编程思想实现 DOM 操作的封装。 了解面向对象编程的一般特征掌握基于构造函数原型对象的逻辑封装掌握基于原型对象实现的继承理解何为原型链及其作用能够处理…

安全测试工具安装指南:在统信UOS上部署Burp Suite

原文链接&#xff1a;安全测试工具安装指南&#xff1a;在统信UOS上部署Burp Suite 大家好&#xff01;在网络安全领域&#xff0c;Burp Suite是一款不可或缺的工具&#xff0c;它提供了从初级映射和分析应用程序攻击面到查找和利用安全漏洞的一系列功能。今天&#xff0c;我将…

Pytorch框架-----torch.tensor(创建张量)

文章目录 前言一、torch.Tensor二、构建tensor1.从Python的list或序列构建2.空张量3.索引和切片来获取和修改一个张量tensor中的内容 前言 torch.Tensor 是包的核心类。如果将其属性 .requires_grad 设置为 True&#xff0c;则会开始跟踪针对 tensor的所有操作。完成计算后&am…

VS引用第三方库

使用Qt开发习惯了&#xff0c;切换来VS环境&#xff0c;居然引用第三方库&#xff0c;都有所不适应&#xff1b;因为之前都是在Qt项目的pro文件里面直接手写配置好第三方库的include目录、lib目录和依赖的lib名称和拷贝dll语句. Vs也一样&#xff0c;如下三步&#xff1a; 第一…

世界顶级名校计算机专业,都在用哪些书当教材?(文末送书)

目录 01《深入理解计算机系统》02《算法导论》03《计算机程序的构造和解释》04《数据库系统概念》05《计算机组成与设计&#xff1a;硬件/软件接口》06《离散数学及其应用》07《组合数学》08《斯坦福算法博弈论二十讲》参与规则 清华、北大、MIT、CMU、斯坦福的学霸们在新学期里…

板块一 Servlet编程:第三节 HttpServletRequest对象全解与请求转发 来自【汤米尼克的JAVAEE全套教程专栏】

板块一 Servlet编程&#xff1a;第三节 HttpServletRequest对象全解与请求转发 一、什么是HttpServletRequest二、接收请求的常用方法三、请求乱码问题四、请求转发&#xff1a;forward五、Request作用域getParameter和getAttribute的区别 在上一节中我们已经学习了完整的Servl…

【Linux】进程地址空间的理解

进程地址空间的理解 一&#xff0c;什么是程序地址空间二&#xff0c;页表和虚拟地址空间三&#xff0c;为什么要有进程地址空间 一&#xff0c;什么是程序地址空间 在我们写程序时&#xff0c;都会有这样下面的内存结构&#xff0c;来存放变量和代码等数据。 一个进程要执行…

【安全狐】Windows隐藏计划任务技术及排查方法

0x00 前置知识 计划任务SCHTASKS命令 SCHTASKSSCHTASKS /Create 参数 SCHTASKS /Create [/S system [/U username [/P [password]]]][/RU username [/RP password]] /SC schedule [/MO modifier] [/D day][/M months] [/I idletime] /TN taskname /TR taskrun [/ST starttim…