【LeetCode】十七、并查集

news2024/9/21 0:47:52

文章目录

  • 1、并查集Union Find
  • 2、并查集find的优化:路径压缩 Quick find
  • 3、并查集union的优化:权重标记

1、并查集Union Find

并查集,一种树形的数据结构,处理不相交的两个集合的合并与查询问题。

【参考:📕经典解释】

引用上面文章的经典解释并查集:

  • 一个集合就像一个江湖门派,他们有一个教主(代表元),集合中每个元素只需要记住自己的上级,而不是教主
  • find即查询某个元素的代表元(教主)
  • union即把两个门派(集合),合并成一个,认一个教主

在这里插入图片描述

例子:

在这里插入图片描述

查find(x)

有个数组array,长度为10,若array[1] = 6,说明1号元素的上级是6号元素。array[6] = 6,说明6号元素的上级是6号元素,即6号是教主。并查集的查:find(x),即找x元素的教主

public int find(int x ) {
	// 如果x位置的值,等于x,说明x就是教主
	if (x == array[x]) {
		return array[x];
	}
	// 如果不是,查x位置的值的上级
	return find(array[x]);
}

也可不用递归:

public int find(int x ) {
	while(x != array[x]) {
		// 查x位置的元素自己的上级
		x = array[x];
	}
	return x;
}

并union(x,y)

两个集合合并,或者说两个门派合并,看似改动很大,其实只要让一个门派的教主给另一个门派的教主当上级即可。因为只关注两个集合的连通性。

// 传入两个门派的元素
public void union(int x, int y) {
	//查教主
	int rootX = find(x);
	int rootY = find(y);
	if (rootX != rootY) {
		// 让Y门派的教主当X门派教主的上级
		array[rootX] = rootY;
	}
}

如下树形,

在这里插入图片描述

对应的数组:数组索引代表元素,数组的值,代表这个位置的元素的上级

在这里插入图片描述
在这里插入图片描述
合并后,比如让第一个集合的教主做合并后新集合的教主:5号的上级不再是自己,变成了1

在这里插入图片描述

2、并查集find的优化:路径压缩 Quick find

用开头引用文章的形象例子,现在要做的就是,防止树形结构过于深,导致查询效率变低,将结果压缩成,只要查一次,就能知道教主是谁:

在这里插入图片描述

总之一句话,防止树太高,期待右边,而不是左边

在这里插入图片描述

想实现这个效果,可以:查询到x元素的根节点(教主)后,直接将x元素的上级改成根节点。

public int QuickFind(int x ) {
	// 如果x位置的值,等于x,说明x就是教主
	if (x == array[x]) {
		return array[x];
	}
	// 如果不是,查x位置的值的上级,等递归回退的时候,把x的上级改成根节点
	return array[x] = find(array[x]);
}

也就是说,第一次find元素x,是没有压缩路径的,第二次才是优化后的效果

3、并查集union的优化:权重标记

和find优化属于同一思想,union两个集合时,防止树过高,比如合并:

在这里插入图片描述
如果这么连,树过高:

在这里插入图片描述
比较两棵树的高度,左边为2,右边为3,因此,高的树原地不动,继续做老大,低的树靠过去,union后的效果:

在这里插入图片描述

核心思想:

在这里插入图片描述

整体代码如下,带权重的union参考:

public class UnionFind {

	const int  N=1005					//指定并查集所能包含元素的个数(由题意决定)
	int pre[N];     					//存储每个结点的前驱结点的数组 
	int rank[N];    					//树的高度,权重
	
	void init(int n) {     				//初始化函数,对录入的 n个结点进行初始化 
	    for(int i = 0; i < n; i++){
	        pre[i] = i;     			//每个结点的上级都是自己 
	        rank[i] = 1;    			//每个结点构成的树的高度为 1 
	    } 
	}

	int find(int x) {
     	//查找结点 x的根结点 
		if (pre[x] == x) { 
			return x ;					//递归出口:x的上级为 x本身,则 x为根结点 
		}  		
	    return find(pre[x]); 			//递归查找 
	} 
	 
	int findQucik(int x) {     			//改进查找算法:完成路径压缩,将 x的上级直接变为根结点,那么树的高度就会大大降低 
	    if (pre[x] == x) {
	    	return x;					//递归出口:x的上级为 x本身,即 x为根结点 
	    }
	    return pre[x] = find(pre[x]);   //此代码相当于先找到根结点 rootx,然后 pre[x]=rootx 
	} 
	
	bool isSame(int x, int y) {     	//判断两个结点是否连通 
	    return find(x) == find(y);  	//判断两个结点的根结点(即代表元)是否相同 
	}
	
	void union(int x,int y) {
	    int rootx = find(x);			//寻找 x的代表元
	    int rooty = find(y);			//寻找 y的代表元
	    if(rootx != rooty) {			//如果 x和 y的代表元一致,说明他们共属同一集合,则不需要合并
		    if(rank[rootx] > rank[rooty]) {		//如果 x的高度大于 y,则令 y的上级为 x
		    	pre[rooty] = rootx;
		    } else if (rank[rootx] < rank[rooty]) {
		    	pre[rootx] = rooty;		//让 x的上级为 y
		    } else {
		    	pre[rooty] = rootx;	    								
		        rank[rootx] += 1;				//如果 x的高度和 y的高度相同,则令 y的高度加1					
			}
		}
	}
}

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

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

相关文章

Linux·基本指令(下)

1. mv 指令 (move) 语法&#xff1a;mv[选项] 源文件或目录 目标文件或目录 功能&#xff1a;将源文件或目录剪贴到一个新位置&#xff0c;或给源文件或目录改名但不会改变其内容 常用选项&#xff1a; -f &#xff1a;force 强制&#xff0c;如果目标文件已经存在&#xff0c;…

Unty 崩溃问题(Burst 1.8.2)

错误代码&#xff1a; Assertion failed on expression: exception SCRIPTING_NULL UnityEngine.StackTraceUtility:ExtractStackTrace () Unity.Burst.BurstCompiler:SendRawCommandToCompiler (string Unity版本&#xff1a;2021.3.17F1&#xff0c;Burst 1.8.2 表现&…

openstack设置IP直接登录,不需要加dashboard后缀

openstack 实验环境&#xff0c;openstack-t版&#xff0c;centos2009 修改配置文件 [rootcontroller ~]# vim /WEBROOT /etc/openstack-dashboard/local_settings #将dashboard去掉 WEBROOT /dashboard/ #改为 WEBROOT /[rootcontroller ~]# vim /etc/httpd/conf.d/openst…

pytorch学习(七):池化层的使用

MaxPool2d&#xff1a; 参数详解&#xff1a; kernel_size: int or tuple。 stride&#xff1a;窗口的步长&#xff0c;默认值是kernel_size的值。&#xff08;卷积层默认值为1&#xff09; dilation&#xff1a;如下图&#xff0c;控制窗口内内元素之间的距离。学名空洞卷积…

浅析stm32启动文件

浅析stm32启动文件 文章目录 浅析stm32启动文件1.什么是启动文件&#xff1f;2.启动文件的命名规则3.stm32芯片的命名规则 1.什么是启动文件&#xff1f; 我们来看gpt给出的答案&#xff1a; STM32的启动文件是一个关键的汇编语言源文件&#xff0c;它负责在微控制器上电或复位…

持续集成05--Gogs的安装与使用

前言 在持续集成/持续部署&#xff08;CI/CD&#xff09;的旅程中&#xff0c;版本控制系统是不可或缺的一环。当我们在使用jenkins&#xff0c;想要达到测试脚本有更新&#xff0c;就让项目自动去进行构建&#xff0c;或者当开发脚本有更新&#xff0c;也可以自动去构建的效果…

graham 算法计算平面投影点集的凸包

文章目录 向量的内积&#xff08;点乘&#xff09;、外积&#xff08;叉乘&#xff09;确定旋转方向numpy 的 cross 和 outernp.inner 向量与矩阵计算示例np.outer 向量与矩阵计算示例 python 示例生成样例散点数据图显示按极角排序的结果根据排序点计算向量转向并连成凸包 基本…

linux中关于环境变量的常用的设置方法

一. linux中设置环境变量的方式 1.使用/etc/environment, 是一个全局的环境变量设置文件&#xff0c;它会影响到所有用户和所有进程。当你需要设置一个全局的环境变量时&#xff0c;应该使用这个文件。这个文件的格式是 KEYvalue&#xff0c;每行一个环境变量。 2. 使用/etc/…

Spring Data Redis + Redis数据缓存学习笔记

文章目录 1 Redis 入门1.1 简介1.2 Redis服务启动与停止&#xff08;Windows&#xff09;1.2.1 服务启动命令1.2.2 客户端连接命令1.2.3 修改Redis配置文件1.2.4 Redis客户端图形工具 2. Redis数据类型2.1 五种常用数据类型介绍 3. Redis常用命令3.1 字符串操作命令3.2 哈希操作…

【学习笔记】虚幻SkeletalMesh学习(一)基础介绍

文章目录 零、前言一、资源介绍1.1 骨架资源1.2 骨架网格体资源 二、UE4中的定义2.1 骨骼数据2.2 模型网格数据 三、渲染3.1 RenderData的初始化3.2 渲染对象的创建3.3 渲染对象的更新3.3.1 游戏线程的更新&#xff08;*FSkeletalMeshObjectGPUSkin::Update*&#xff09;3.3.2 …

大模型“重构”教育:解构学习奥秘,推动教育普惠

大模型“重构”千行百业系列选题 生成式人工智能的热潮&#xff0c;为AI领域的发展注入新的活力&#xff0c;而“赋能千行百业”已经成为人们普遍对于人工智能和大模型的全新理解。 人工智能和大模型技术的迅猛发展正在以前所未有的速度深刻改变着各个行业。正如专家所预测&a…

《昇思25天学习打卡营第23天|onereal》

第23天学习内容简介&#xff1a; ----------------------------------------------------------------------------- 本案例基于MindNLP和ChatGLM-6B实现一个聊天应用。 1 环境配置 配置网络线路 2 代码开发 下载权重大约需要10分钟 ------------------------------- 运…

汇总国内镜像提供了Redis的下载地址

文章目录 1. 清华大学开源软件镜像站&#xff1a;2. 中国科技大学开源软件镜像&#xff1a;3. 阿里云镜像&#xff1a;4. 华为云镜像&#xff1a;5. 腾讯云镜像&#xff1a;5. 官方GitHub仓库&#xff08;虽然不是镜像&#xff0c;但也是一个可靠的下载源&#xff09;&#xff…

XX2104 培训【C++解决】

描述 某培训机构的学员有如下信息&#xff1a; 姓名&#xff08;字符串&#xff09; 年龄&#xff08;周岁&#xff0c;整数&#xff09; 去年 NOIP 成绩&#xff08;整数&#xff0c;且保证是 5 的倍数&#xff09; 经过为期一年的培训&#xff0c;所有同学的成绩都有所提高&…

【数据结构与算法】数据结构(Data Structure)的基本概念及其研究对象

什么是程序 算法数据结构程序 —— Nicklaus Wirth(尼古拉斯沃斯) Niklaus Wirth是一位著名的计算机科学家&#xff0c;他提出了"程序算法数据结构"的观点。他认为&#xff0c;程序不仅仅是执行特定任务的一段代码&#xff0c;而是由算法和数据结构两部分组成的。算法…

Linux--线程同步

目录 0.上篇 1. 线程同步概念 2.认识条件变量 2.1条件变量的概念 2.2认识接口 2.3写一个测试代码 3.生产者消费者模型 3.1概念部分 1.基本概念 2.主要问题 3.优点 4.思考切入点&#xff08;321原则&#xff09; 3.2编写基于BlockingQueue的生产者消费者模型&…

js执行机制----事件循环

前言 问题 一般情况下,我们都认为js是顺序执行的 但是遇到下列情况 setTimeout(function(){console.log(定时器开始啦) });new Promise(function(resolve){console.log(马上执行for循环啦);for(var i 0; i < 10000; i){i 99 && resolve();} }).then(function(…

MySQL数据库查询索引失效场景

在连表情况下,如果排序字段涉及到了两个表,排序字段将无法走索引. 加上第二个排序字段之后,走全表扫描了. 或者尽量让两次排序都用同一个表的字段,这样可以建联合索引让排序也能走索引.&#xff08;不想建联合索引的话&#xff0c;可以第二次排序用表id&#xff0c;这样单个的…

天池AI大模型技术提升营火热上线,四重好礼等你来拿!

目标锁定&#xff0c;加速成长&#xff0c;四大活动玩法助您提升技术&#xff0c;赢取四重好礼&#xff1a; 【活动一】完成3步学习任务&#xff0c;赢取定制加湿器 【活动二】邀请好友报名指定学习赛&#xff0c;累计助力赢苹果iPad、大疆无人机、韶音蓝牙耳机等好礼 【活动三…

华为1000人校园实验记录

在这里插入代码片1000人校园区网设计 1、配置Eth-trunk实现链路冗余 vlan 900 管理WLAN #接入SW8 操作&#xff1a;sys undo in en sysname JR-SW8 int Eth-Trunk 1 mode lacp-static trunkport g0/0/1 0/0/2 port link-type trunk port trunk allow-pass vlan 200 900 qu vla…