当前位置: 首页 > news >正文

并查集(不相交集)详解

目录

一.并查集

1.什么是并查集

2.并查集的基本操作

3.并查集的应用

4.力扣上的题目

二.三大操作

1.初始化

2.查找

 3.合并

三.省份数量

1.题目描述

2.问题分析

3.代码实现

四.冗余连接

1.题目描述

2.问题分析

3.代码实现


一.并查集

1.什么是并查集

并查集(Disjoint-set Union 或 Union-find)是一种数据结构,用于维护一些不相交(disjoint)的集合,支持合并两个集合以及判断两个元素是否属于同一个集合。

并查集可以使用树来实现,每个集合可以看做是一棵树,代表元素是根节点。使用路径压缩可以减少查找操作的时间复杂度,使用按秩合并可以减少合并操作的时间复杂度,使得并查集的时间复杂度可以达到近乎常数级别,因此在一些算法中广泛应用,比如 Kruskal 算法和 Tarjan 算法。

2.并查集的基本操作

  1. 初始化:将每个元素初始化为单独的集合,每个集合的代表元素就是自己;
  2. 查找:给定一个元素,找到它所属的集合的代表元素;
  3. 合并:将两个集合合并成一个集合,即将其中一个集合的代表元素作为另一个集合的代表元素的子节点。

3.并查集的应用

并查集是一种用于维护集合(组)的数据结构,它通常用于解决一些离线查询、动态连通性和图论等相关问题。

其中最常见的应用场景是解决图论中的连通性问题,例如判断图中两个节点是否连通、查找图的连通分量、判断图是否为一棵树等等。并查集可以快速地合并两个节点所在的集合,以及查询两个节点是否属于同一个集合,从而有效地判断图的连通性。

并查集还可以用于解决一些离线查询问题,例如静态连通性查询和最小生成树问题,以及一些动态连通性问题,例如支持动态加边和删边的连通性问题。

总之,如果需要维护集合(组)的连通性信息,就可以考虑使用并查集。

现在举一个现实中的问题,判断一个人是否属于一个家族,通常一个家族里面两个人可能不是彼此认识的,但是A和B是亲属关系,B和C是亲属关系,此时我们可以判断出A和C就是亲属关系

 由于家族关系可能错综复杂,这个时候我们是否可以找一个代表,这个人来代表这个家族,比如选择A来代表家族A,D来代表家族B,那么只要你和A有关系,你就是属于A家族的,你和D有关系,你就是属于B家族的

并查集就是解决这样的问题的.

4.力扣上的题目

以下是一些力扣(LeetCode)上关于并查集(Union Find)的题目:

  1. 朋友圈(547) https://leetcode-cn.com/problems/friend-circles/

  2. 冗余连接(684) https://leetcode-cn.com/problems/redundant-connection/

  3. 冗余连接 II(685) https://leetcode-cn.com/problems/redundant-connection-ii/

  4. 岛屿数量(200) https://leetcode-cn.com/problems/number-of-islands/

  5. 连通网络的操作次数(1319) https://leetcode-cn.com/problems/number-of-operations-to-make-network-connected/

  6. 表示数值的字符串(剑指 Offer 20) https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/

  7. 最大连通面积(面试题 16.19) https://leetcode-cn.com/problems/pond-sizes-lcci/

  8. 能否连接形成区域(面试题 16.19) https://leetcode-cn.com/problems/pond-sizes-lcci/

  9. 合并账户(721) https://leetcode-cn.com/problems/accounts-merge/

  10. 判断能否形成等差数列(1502) https://leetcode-cn.com/problems/can-make-arithmetic-progression-from-sequence/

以上是一些力扣上的并查集题目,建议在练习时,先自己尝试思考解法,如果卡在某个地方,可以查看题解或者向其他程序员求助。

二.三大操作

1.初始化

我们把数组初始化-1,具体的作用我们之后再来分析具体的用处,具体含义就是,这个负数的相反数为这棵树的高度-1

    public void init(int[] parent) {//初始值设置为-1for (int i = 0; i < parent.length; ++i) {parent[i] = -1;}}

2.查找

不进行路径压缩的查找简单粗暴的,它的目的就是为了找到结点i的根结点,直接看代码

    public int find(int[] parent, int i) {if (parent[i] < 0) {//当前结点为根结点,终止return i;} else {return parent[i];     //返回父节点}}

这个时候我们来研究一下进行路径压缩的查找方式,我们需要合并0和4,如果我们只是粗暴的合并的话,这个时候0指向3,这个时候其实的查询长度就是越来越长,时间复杂度为O(n)

 所以这个时候我们不进行路径压缩,压缩之后的图是这样的,这个时候时间复杂度大大降低,我们每次查找根结点的时候,只需要查找一次(递归一次)便可以找到根结点

进行路径压缩的查找方法要进行两个操作,最终目的肯定还是要找寻到根结点,但是其次他也进行了路径的压缩,例如下图一样,把本来的4指向3,修改成了4指向了2,其实可以精炼成一句话:找到根结点,并且把路径上所有节点的父亲结点修改为根结点.这样树的高度就变成了1(只含有一个结点(根结点)的高度为0).

    public int find(int[] parent, int i) {if (parent[i] < 0) {//当前结点为根结点,终止return i;} else {parent[i] = find(parent, parent[i]);  //父节点设为根结点return parent[i];     //返回父节点}}

 3.合并

合并操作也可以简单粗暴的进行合成,我们只需要找到各自的祖先,任意的将一个合并到另一个上边即可,直接看代码

    public void union(int[] parent, int i, int j) {int i_parent = find(parent, i);//寻找i的根结点int j_parent = find(parent, j);//寻找j的根结点parent[i_parent]=j_parent;//将根结点为i_parent的树合并到根结点j_parent上}

如果我们这个时候进行合并可能会出现这种情况,也就是一个高度较大的数合并到了一个高度较小的树上面,这个时候树的高度就会增加,如果我们是高度小的树合并到高度较大的树上边(两颗树的高度不相等),这个时候树的高度便不会增加,自然查找的时候会更加快速的查找到.

进行按秩(树的高度)进行合并

这种合并方式就是为了解决上面所提到的问题,合并是便会是这种情况,但是我们如果判断两棵树的高度大小呢,这个时候就可以解释以下初始化的为-1的目的了,一:如果当前结点的值为负数,可以判断当前结点为根结点,二.当前结点越小(也就是相反数越大),说明当前树的高度越大,我们只需要把更大的根结点的值合并到更小的根结点值上,便可以解决这个问题了.

这个时候存在一个特殊情况,也就是两棵树的高度一样高.这个时候无论如何进行合并,树的高度度会增加,因此这个时候我们可以把一个根结点合并到另一个根结点上,并把合并到的根结点的值减一

    public void union(int[] parent, int i, int j) {int i_parent = find(parent, i);//寻找i的根结点int j_parent = find(parent, j);//寻找j的根结点if (i_parent != j_parent) {//此时的根结点相同,没有合并的必要if (parent[i_parent] < parent[j_parent]) {//此时表示i_parent的秩比j_parent的秩大parent[j_parent] = i_parent;//把j_parent合并到i_parent上} else {if (parent[i_parent] == parent[j_parent]) {parent[j_parent]--;}parent[i_parent] = j_parent;//把i_parent合并到j_parent上}}}

三.省份数量

1.题目描述

n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

力扣:力扣

2.问题分析

这是一道很典型的并查集问题,题目的意思就是城市之间相连就是一个省份,把相连的城市合并为一颗树,最终就是寻找有多少个根结点(有多少颗树),也就是parent[i]有多少个是小于0的值,就是一棵树,最终返回数量就可以了

3.代码实现

    public void init(int[] parent) {//初始值设置为-1for (int i = 0; i < parent.length; ++i) {parent[i] = -1;}}public int find(int[] parent, int i) {if (parent[i]<0) {return i;} else {parent[i] = find(parent, parent[i]);  //父节点设为根结点return parent[i];     //返回父节点}}public void union(int[] parent, int i, int j) {int i_parent = find(parent, i);//寻找i的祖先int j_parent = find(parent, j);//寻找j的祖先if (i_parent != j_parent) {//此时的祖先相同,没有合并的必要if (parent[i_parent] < parent[j_parent]) {//此时表示i_parent的秩比j_parent的秩大parent[j_parent] = i_parent;//把j_parent合并到i_parent上} else {if (parent[i_parent] == parent[j_parent]) {parent[j_parent]--;}parent[i_parent] = j_parent;//把i_parent合并到j_parent上}}}public int findCircleNum(int[][] isConnected) {int[] parent = new int[isConnected.length];init(parent);for (int i = 0; i < isConnected.length; ++i) {for (int j = i + 1; j < isConnected[0].length; ++j) {if (isConnected[i][j] == 1) {union(parent, i, j);}}}int cnt = 0;for (int i = 0; i < parent.length; ++i) {if (parent[i] < 0)cnt++;}return cnt;}

四.冗余连接

1.题目描述

树可以看成是一个连通且 无环 的 无向 图。

给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 aibi 之间存在一条边。

请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的边。

力扣:力扣

2.问题分析

题目的意思就是不能出现环,也就是如果两个两个点已经连通了,这个时候不能再在这两个点添加一条边,这个时候就冗余了,我们都知道一个连通分量有n个顶点,n-1条边,而这道题一共有n条边,我们需要寻找的就是这一条冗余的边,当find(parent,i,j)的根结点一样的时候,这个时候这两个顶点之间的边一定是冗余的,找到这样的一条边即可.

3.代码实现

    public void init(int[] parent) {for (int i = 0; i < parent.length; ++i) {parent[i] = -1;}}public int find(int[] parent, int i) {if (parent[i] < 0)return i;else {parent[i] = find(parent, parent[i]);return parent[i];}}public void union(int[] parent, int i, int j) {int i_parent = find(parent, i);int j_parent = find(parent, j);if (i_parent != j_parent) {if (parent[i_parent] < parent[j_parent]) {parent[j_parent] = i_parent;} else {if (parent[i_parent] == parent[j_parent]) {parent[j_parent]--;}parent[i_parent] = j_parent;}}}public int[] findRedundantConnection(int[][] edges) {int[] parent = new int[edges.length+1];init(parent);for (int i = 0; i < edges.length; ++i) {if (find(parent, edges[i][0]) != find(parent, edges[i][1])) {union(parent, edges[i][0], edges[i][1]);} else {return edges[i];}}return null;}

相关文章:

并查集(不相交集)详解

目录 一.并查集 1.什么是并查集 2.并查集的基本操作 3.并查集的应用 4.力扣上的题目 二.三大操作 1.初始化 2.查找 3.合并 三.省份数量 1.题目描述 2.问题分析 3.代码实现 四.冗余连接 1.题目描述 2.问题分析 3.代码实现 一.并查集 1.什么是并查集 并查集&…...

10个最频繁用于解释机器学习模型的 Python 库

文章目录什么是XAI&#xff1f;可解释性实践的步骤技术交流1、SHAP2、LIME3、Eli54、Shapash5、Anchors6、BreakDown7、Interpret-Text8、aix360 (AI Explainability 360)9、OmniXAI10、XAI (eXplainable AI)XAI的目标是为模型的行为和决定提供有意义的解释&#xff0c;本文整理…...

final关键字:我偏不让你继承

哈喽&#xff0c;小伙伴们大家好&#xff0c;我是兔哥呀&#xff0c;今天就让我们继续这个JavaSE成神之路&#xff01; 这一节啊&#xff0c;咱们要学习的内容是Java所有final关键字。 之前呢&#xff0c;我们学习了继承&#xff0c;这大大提高了代码的灵活性和复用性。但是总…...

8大主流编程语言的适用领域,你可能选错了语言

很多人学编程经常是脑子一热然后就去网上一搜资源就开始学习了&#xff0c;但学到了后面发现目前所学的东西并不是自己最喜欢的&#xff0c;好像自己更喜欢另一个技术&#xff0c;感觉自己学错了&#xff0c;于是乎又去学习别的东西。 结果竹篮打水一场空&#xff0c;前面所付…...

关于Python库的问题

关于Python库的问题 问题1&#xff1a; ModuleNotFoundError: No module named ‘requests’ Python库 Pycharm使用Requests库时报错&#xff1a; No module named requests’解决方法 未安装requests库&#xff0c;使用"pip install requests"命令安装 依然提示P…...

好记性不如烂笔头(2)

概述&#xff1a;用来记录一些小技巧。 1.查看MyBatis执行的sql 类&#xff1a;org.apache.ibatis.mapping.MappedStatement方法&#xff1a;getBoundSql(Object parameterObject)在IDEA的Evaluate Expression查看sql&#xff1a;boundSql.getSql() 2.maven仓库地址为https&…...

Java for循环嵌套for循环,你需要懂的代码性能优化技巧

前言 本篇分析的技巧点其实是比较常见的&#xff0c;但是最近的几次的代码评审还是发现有不少兄弟没注意到。 所以还是想拿出来说下。 正文 是个什么场景呢&#xff1f; 就是 for循环 里面还有 for循环&#xff0c; 然后做一些数据匹配、处理 这种场景。 我们结合实例代码来…...

关于我拒绝了腾讯测试开发岗offer这件事

2022年刚开始有了向要跳槽的想法&#xff0c;之前的公司不能算大厂但在重庆也算是数一数二。开始跳槽的的时候我其实挺犹豫的 其实说是有跳槽的想法在2022年过年的时候就有了&#xff0c;因为每年公司3月会有涨薪的机会&#xff0c;所以想着看看那能不能涨&#xff08;其实还是…...

从GPT到GPT-3:自然语言处理领域的prompt方法

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…...

Git代码提交规范

Git 代码规范Git 每次提交代码&#xff0c;都是需要写 Commit message&#xff08;提交说明&#xff09;&#xff0c;否则就不允许提交。Commit message 的格式 (三部分)&#xff1a;Heaher ----- 必填type ---必需scope --- 可选subject --- 必需Body ---- 可省略Footer ---- …...

【JavaScript速成之路】JavaScript内置对象--Math和Date对象

&#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f525;系列专栏&#xff1a;【JavaScript速成之路】 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 文章目录前言1&#xff0c;Math对象1.1&#xff0c;常用属性方法1.1.1&#xff0c;获取x的…...

(自用POC)Fortinet-CVE-2022-40684

本文转载于&#xff1a;https://mp.weixin.qq.com/s?__bizMzIzNDU5Mzk2OQ&mid2247485332&idx1&sn85931aa474f1ae2c23a66bf6486eec63&chksme8f54c4adf82c55c44bc7b1ea919d44d377e35a18c74f83a15e6e20ec6c7bc65965dbc70130d&mpshare1&scene23&srcid…...

ConvNeXt V2实战:使用ConvNeXt V2实现图像分类任务(二)

文章目录训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整算法设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法运行以及结果查看测试热力图可视化展示完…...

【人工智能与深度学习】基于正则化潜在可变能量的模型

【人工智能与深度学习】基于正则化潜在可变能量的模型 正则化潜变量能量基础模型稀疏编码FISTALISTA稀疏编码示例卷积稀疏编码自然图像上的卷积稀疏编码可变自动编码器正则化潜变量能量基础模型 具有潜在变量的模型能够生成预测分布 y ‾ \overline{y}...

【Leetcode——排序的循环链表】

&#x1f60a;&#x1f60a;&#x1f60a; 文章目录一、力扣题之排序循环链表二、解题思路1. 使用双指针法2、找出最大节点&#xff0c;最大节点的下一个节点是最小节点&#xff0c;由此展开讨论总结一、力扣题之排序循环链表 题目如下&#xff1a;航班直达&#xff01;&#…...

ChatGPT研究分享:机器第一次开始理解人类世界目录

0、为什么会对ChatGPT感兴趣一开始&#xff0c;我对ChatGPT是没什么关注的&#xff0c;无非就是有更大的数据集&#xff0c;完成了更大规模的计算&#xff0c;所以能够回答更多的问题。但后来了解到几个案例&#xff0c;开始觉得这个事情并不简单。我先分别列举出来&#xff0c…...

【linux】Linux基本指令(上)

前言&#xff1a; 在之前我们已经简单了介绍了一下【Linux】&#xff0c;包括它的概念&#xff0c;由来啊等进行了讲解&#xff0c;接下来我们就将正式的踏入对其的学习&#xff01;&#xff01;&#xff01; 本文目录&#x1f449;操作系统的概念1.命令的语法1.1命令介绍1.2选…...

程序员必会技能—— 使用日志

目录 1、为什么要使用日志 2、自定义日志打印 2.1、在程序中得到日志对象 2.2、使用日志对象打印日志 2.3、日志格式 3、日志的级别 3.1、日志级别的分类 3.2、日志级别的设置 4、持久化日志 5、更简单的日志输出——lombok 5.1、如何在已经创建好的SpringBoot项目中添加…...

生成项目的包依赖文件requirements.txt

目录生成项目的包依赖文件requirements.txtrequirements.txt文件怎么来&#xff1f;使用pipreqs第三方库requirements.txt文件使用requirements.txt生成项目的包依赖文件requirements.txt 在安装部署代码时或者使用别人的项目时&#xff0c;会需要安装项目的依赖包&#xff0c…...

安卓渐变的背景框实现

安卓渐变的背景框实现1.背景实现方法1.利用PorterDuffXfermode进行图层的混合&#xff0c;这是最推荐的方法&#xff0c;也是最有效的。2.利用canvas裁剪实现&#xff0c;这个方法有个缺陷&#xff0c;就是圆角会出现毛边&#xff0c;也就是锯齿。3.利用layer绘制边框1.背景 万…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...