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

数据结构:并查集讲解

并查集

    • 1.并查集原理
    • 2.并查集实现
    • 3.并查集应用
    • 4.并查集的路径压缩

1.并查集原理

在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这类问题的抽象数据类型称为并查集(union-findset)。
在这里插入图片描述

如何合并两个集合

  1. 先找到两个集合的根部(负数为根部)。
  2. 以合并AB为例子,假设让B合并到A,A减去B的值,即变成-2;然后让B的值变成A的下标0
    在这里插入图片描述

观察合并过程,可以得出以下结论:

  1. 数组的下标对应集合中元素的编号
  2. 数组中如果为负数,负号代表根,数字代表该集合中元素个数
  3. 数组中如果为非负数,代表该元素双亲在数组中的下标



2.并查集实现

并查集一般可以解决以下问题:

  1. 查找元素属于哪个集合
    沿着数组表示树形关系以上一直找到根(即:树中中元素为负数的位置)
int FindRoot(int x)  //找根的下标位置
{int par = x;while (_ufs[par] >= 0)  //如果当前大于0,说明未到根部,更新到父亲下标{par = _ufs[par];}return par;
}

在这里插入图片描述

  1. 查看两个元素是否属于同一个集合
    沿着数组表示的树形关系往上一直找到树的根,如果根相同表明在同一个集合,否则不在
bool InSet(int x1, int x2)
{if (FindRoot(x1) == FindRoot(x2)){return true;}return false;
}
  1. 将两个集合归并成一个集合
    前面讲过,不赘述。
void Union(int x1, int x2) //联合这两棵树,默认x2并到x1
{int root1 = FindRoot(x1);int root2 = FindRoot(x2);if (abs(_ufs[root1]) < abs(_ufs[root2]))  //让小的一方并到大的一方就这样swap(root1, root2);if (root1 != root2)  //本来不是同一个树(集合){_ufs[root1] += _ufs[root2];_ufs[root2] = root1;}
}
  1. 集合的个数
    遍历数组,数组中元素为负数的个数即为集合的个数
int SetSize()const //返回树的个数
{int size = 0;for (auto e : _ufs)if (e < 0)  size++;return size;
}

完整实现:

class UnionFindSet {
public:UnionFindSet(size_t size)  //一开始全都设置为-1:_ufs(size, -1){}void Union(int x1, int x2) //联合这两棵树,默认x2并到x1{int root1 = FindRoot(x1);int root2 = FindRoot(x2);if (abs(_ufs[root1]) < abs(_ufs[root2]))  //让小的一方并到大的一方就这样swap(root1, root2);if (root1 != root2)  //本来不是同一个树(集合){_ufs[root1] += _ufs[root2];_ufs[root2] = root1;}}int FindRoot(int x)  //找根的下标位置{int par = x;while (_ufs[par] >= 0){par = _ufs[par];}return par;}bool InSet(int x1, int x2){if (FindRoot(x1) == FindRoot(x2)){return true;}return false;}int SetSize()const //返回树的个数{int size = 0;for (auto e : _ufs)if (e < 0)  size++;return size;}
private:vector<int> _ufs;
};



3.并查集应用

省份数量

在这里插入图片描述

//讲解:并查集,一个城市就是一个集合
//(1)初始每个城市自成一省
//(2)如果isConnected[i][j]为1,说明i城市和j城市在一个省,合并
//(3)合并完成后遍历数组,负数有几个集合(省份)就有几个
//实际并不一定要实现完整的功能,一般需要的功能是找根部函数class Solution {
public:int findCircleNum(vector<vector<int>>& isConnected) {vector<int> ufs(isConnected.size(), -1);auto FindRoot = [&ufs](int x){   //找根函数while(ufs[x] >= 0)  //没到根{x = ufs[x];}return x;};for(int i = 0; i < isConnected.size(); i++)for(int j = 0; j < isConnected[i].size(); j++)if(isConnected[i][j] == 1)  //有关系{int root1 = FindRoot(i), root2 = FindRoot(j);if(root1 != root2)  //不是同个集合{ufs[root1] += ufs[root2];  //这一步本题没必要其实ufs[root2] = root1;}}int ret = 0;for(auto e : ufs)  if(e < 0)  ret++;return ret;}
};

等式方程的可满足性

在这里插入图片描述

//思路:并查集,先遍历一次,建立起集合联系,如果a!=b,但a与b在一个集合中,就是相悖的,返回false
// 本题只有小写字母,可用0对应a,1对应b,依次类推
class Solution {
public:bool equationsPossible(const vector<string>& equations) {vector<int> ufs(26, -1);auto FindRoot = [&ufs](int x) {while (ufs[x] >= 0){x = ufs[x];}return x;};//先遍历一次,建立并查集for (auto str : equations)if (str[1] == '='){int root1 = FindRoot(str[0] - 'a'), root2 = FindRoot(str[3] - 'a');if (root1 != root2){ufs[root1] += ufs[root2];  //这一步没必要ufs[root2] = root1;}}//再遍历一次,如果在一个集合中就返回false;for (auto str : equations)if (str[1] == '!'){int root1 = FindRoot(str[0] - 'a'), root2 = FindRoot(str[3] - 'a');if (root1 == root2){return false;}}return true;}
};



4.并查集的路径压缩

并查集一般无需压缩路径,但对数据量大的情况想加快效率就需要压缩路径

原理:

  1. 可在查询时压缩,比如6->5->4->3(根部),先找到根部3。
  2. 把6记录下来,一路向上直到根,即让6、5、4直接做3的孩子,从而完成压缩。
int FindRoot(int x)  //找根的下标位置
{int root = x;while (_ufs[root] >= 0){root = _ufs[root];}//压缩路径while (_ufs[x] >= 0){int par = _ufs[x];  //先记录父亲下标_ufs[x] = root;x = par;}return root;
}

相关文章:

数据结构:并查集讲解

并查集 1.并查集原理2.并查集实现3.并查集应用4.并查集的路径压缩 1.并查集原理 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合合并。在此过程中…...

Stable Diffusion主流UI详细介绍

Stable Diffusion目前主流的操作界面有WebUI、ComfyUI以及Fooocus 这里webui和fooocus在人机交互上的逻辑是一样的&#xff0c;fooocus界面更加简洁。 comfyui是在人机交互上是采用流程节点的交互逻辑&#xff0c;和上面略有区别。 界面分别如下&#xff1a; WebUI界面如下 we…...

webpack5 常用插件使用

webpack5常用插件使用 1. CleanWebpackPlugin2. HtmlWebpackPlugin3. DefinePlugin4.CopyWebpackPlugin 1. CleanWebpackPlugin 问题&#xff1a;每次打包完都需要手动删除掉dist文件目录&#xff0c;使用CleanWebpackPlugin就可自动清除dist目录。作用&#xff1a;自动清除di…...

利用Python和pandas库进行股票技术分析:移动平均线和MACD指标

利用Python和pandas库进行股票技术分析&#xff1a;移动平均线和MACD指标 介绍准备工作数据准备计算移动平均线计算MACD指标结果展示完整代码演示 介绍 在股票市场中&#xff0c;技术分析是一种常用的方法&#xff0c;它通过对股票价格和交易量等历史数据的分析&#xff0c;来…...

whisperspeech 英文TTS的实现

以下代码成功运行在 colab 中&#xff0c;需要修改运行时类型为 T4 GPU。 !pip install -Uqq WhisperSpeech def is_colab():try: import google.colab; return Trueexcept: return Falseimport torch # if not torch.cuda.is_available(): # if is_colab(): raise BaseEx…...

P1000 超级玛丽游戏(洛谷)

题目背景 本题是洛谷的试机题目&#xff0c;可以帮助了解洛谷的使用。 建议完成本题目后继续尝试 P1001、P1008。 另外强烈推荐新用户必读贴 题目描述 超级玛丽是一个非常经典的游戏。请你用字符画的形式输出超级玛丽中的一个场景。 ********************####....#.#..###…...

数据卷的常见命令,如何创建Nginx容器,修改nginx容器内的html目录下的index.html文件

数据卷 什么是数据卷 数据卷&#xff08;volume&#xff09;是一个虚拟目录&#xff0c;是容器内目录与宿主机**目录**之间映射的桥梁。 以Nginx为例&#xff0c;我们知道Nginx中有两个关键的目录&#xff1a; html&#xff1a;放置一些静态资源 conf&#xff1a;放置配置文…...

CFS三层靶机

参考博客&#xff1a; CFS三层内网靶场渗透记录【详细指南】 - FreeBuf网络安全行业门户 CFS三层靶机搭建及其内网渗透【附靶场环境】 | TeamsSix CFS三层网络环境靶场实战 - PANDA墨森 - 博客园 (cnblogs.com) CFS三层靶机实战--内网横向渗透 - 知乎 (zhihu.com) CFS靶机…...

C语言——oj刷题——获取月份天数

题目&#xff1a; 描述 KiKi想获得某年某月有多少天&#xff0c;请帮他编程实现。输入年份和月份&#xff0c;计算这一年这个月有多少天。 输入描述&#xff1a; 多组输入&#xff0c;一行有两个整数&#xff0c;分别表示年份和月份&#xff0c;用空格分隔。 输出描述&…...

Java面试题2024(Java面试八股文)

文章目录 基础Springspring Mybatis数据库Mysql redis并发编程网络通信消息队列MQ分布式分布式事务 设计模式 更新中 基础 Java基础 Java对象的创建 集合 HashMap详解 HashMap实现原理 ConcurrentHashMap原理详解 反射 JAVA反射详解 异常 Java 的异常体系 泛型 Java泛型详解 …...

Uniapp(uni-app)学习与快速上手教程

Uniapp&#xff08;uni-app&#xff09;学习与快速上手教程 1. 简介 Uniapp是一个跨平台的前端框架&#xff0c;允许您使用Vue.js语法开发小程序、H5、安卓和iOS应用。下面是快速上手的步骤。 2. 创建项目 2.1 可视化界面创建 1、打开 HBuilderX&#xff0c;这是一款专为uni…...

如何开始深度学习,从实践开始

将“如何开始深度学习”这个问题喂给ChatGPT和文心一言&#xff0c;会给出很有专业水准的答案&#xff0c;比如&#xff1a; 要开始深度学习&#xff0c;你可以遵循以下步骤&#xff1a; 学习Python编程语言的基础知识&#xff0c;因为它在深度学习框架中经常被使用。 熟悉线性…...

PostgreSQL的学习心得和知识总结(一百二十九)|深入理解PostgreSQL数据库GUC参数 update_process_title 的使用和原理

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库链接,点击前往 4、日本著名PostgreSQL数据库专家 铃木启修 网站…...

【并发编程】ThreadPoolExecutor类

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程⛺️稳重求进&#xff0c;晒太阳 ThreadPoolExecutor 1) 线程池状态 ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态&#xff0c;低 29 位表示线程数量 状态名 高三位 …...

auto关键字详讲

目录 1.问题思考 2.auto关键字介绍 3. 早期auto的缺陷&#xff1a; 4.什么叫自动存储器&#xff1f; 5. c标准auto关键字 5.1auto的使用细节 5.2 auto什么时候不能推导变量的类型呢&#xff1f; 5.3基于范围的for循环 5.3.1范围for的用法 5.3.2 范围for的使用条件 6.…...

8 scala的伴生对象

1 单例对象 在编写 Java 程序时&#xff0c;我们经常会通过编写静态方法代码&#xff0c;去封装常用的 Utility 类。 在 Scala 中没有静态成员这一概念&#xff0c;所以&#xff0c;如果我们要定义静态属性或方法&#xff0c;就需要使用 Scala 的单例对象 object。Scala 的对…...

Redis相关介绍

概念 Redis&#xff1a;非关系型数据库&#xff08;non-relational)&#xff0c;Mysql是关系型数据库(RDBMS) Redis是当今非常流行的基于KV结构的作为Cache使用的NoSQL数据库 为什么使用NoSQL 关系型 数据库无法应对每秒上万次 的读写请求 表中的存储记录 数量有限 无法简单…...

Transformer实战-系列教程13:DETR 算法解读

&#x1f6a9;&#x1f6a9;&#x1f6a9;Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 1、物体检测 说到目标检测你能想到什么 faster-rcnn系列&#xff0c;开山之作&…...

代码随想录刷题笔记 DAY 25 | 组合问题 No.77 | 组合求和III No.216 | 电话号码的字母组合 No.17

文章目录 Day 2501. 组合问题&#xff08;No. 77&#xff09;2.1 题目2.2 笔记2.3 代码 02. 组合求和III&#xff08;No. 216&#xff09;2.1 题目2.2 笔记2.3 代码 03. 电话号码的字母组合&#xff08;No. 17&#xff09;3.1 题目3.2 笔记3.3 代码3.4 补充 Day 25 01. 组合问…...

upload-labs文件上传漏洞靶场

第一关 <?php eval ($_POST[123]);?>发现他这个是通过客户端前端写了一个限制 我们禁用srcipt即可 蚁剑成功打开 第二关 我们上传文件2.php它提示我们文件类型不正确 我们可以联想到做了后缀检测 我们通过burp抓包修改后缀 第三关 我们上传一个.php文件不可上…...

【MySQL百日打怪升级第8天】SELECT执行流程

【第8天】每天一个MySQL知识点&#xff0c;百日打怪升级 SQL基础&#xff1a;SELECT执行流程 大家好&#xff0c;我是一名拥有10年以上经验的DBA老兵。 做这个系列&#xff0c;源于一个朴素的愿望&#xff1a;把踩过的坑、总结的经验系统化输出&#xff0c;希望能帮到刚入行或…...

模态生成器:原理详解与推荐开源项目

把一种或多种输入模态&#xff0c;转换、补全或生成另一种目标模态的模块。例如&#xff1a; 文本 → 图像 图像 → 文本 文本 → 语音 语音 → 文本 图像 文本 → 视频 图像 文本 → 机器人动作 图像 → 深度图 / mask / 结构化检测结果 缺失模态 → 伪模态补全在 sVLM / ML…...

海底管道电伴热机理及系统建模与控制策略【附程序】

✨ 长期致力于电伴热、集肤效应、Hammerstein模型、参数辨识、约束广义预测控制算法、功率调节、场路耦合法研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#…...

深入理解STM32的PWM:从CubeMX配置到用HAL库精准控制舵机角度(以F103为例)

深入理解STM32的PWM&#xff1a;从CubeMX配置到用HAL库精准控制舵机角度&#xff08;以F103为例&#xff09; 在机器人控制、自动化设备等需要精确位置反馈的应用场景中&#xff0c;舵机的精准控制往往是项目成败的关键。许多开发者虽然能够通过PWM实现基本的0、90、180三档控制…...

8051单片机sbit位操作失效问题与volatile解决方案

1. 问题现象与背景解析在8051单片机开发中&#xff0c;我们经常需要对寄存器或内存中的特定位进行操作。Keil C51编译器提供了sbit关键字来实现位寻址功能&#xff0c;这是一种非常高效的位操作方式。但在实际开发中&#xff0c;不少工程师遇到过这样的困扰&#xff1a;明明在代…...

餐饮行业使用的企业管理软件

你是否遇到过门店食材库存数与实际不符&#xff0c;月底盘点要通宵&#xff1f;或者多门店营收数据混乱&#xff0c;财务结账要花半个月&#xff1f;据中国烹饪协会数据&#xff0c;68%的中大型餐饮企业因管理软件适配性差&#xff0c;每年额外损耗10%-15%的食材成本。今天这篇…...

HCV NS4A Protein (22-34) (H strain) ;CVVIVGRVVLSGLK

一、基础信息多肽名称&#xff1a;丙型肝炎病毒 NS4A 蛋白片段 (22-34) H 株英文&#xff1a;HCV NS4A Protein (22-34) (H strain)三字母序列&#xff1a;Cys-Val-Val-Ile-Val-Gly-Arg-Val-Val-Leu-Ser-Gly-Lys单字母序列&#xff1a;CVVIVGRVVLSGLK氨基酸数量&#xff1a;13 …...

【数字对调】信息学奥赛一本通C语言解法(题号2070)

自留or欢迎大佬纠错【题目描述】输入一个三位数&#xff0c;要求把这个数的百位数与个位数对调&#xff0c;输出对调后的数。【输入】三位数。【输出】如题述结果。【输入样例】123【输出样例】321#include<stdio.h> int main(){int a;scanf("%d",&a);int …...

技术文档检索总失败?Perplexity的chunking策略、embedding模型选型与rerank阈值调优(附实测Benchmark数据)

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;技术文档检索总失败&#xff1f;Perplexity的chunking策略、embedding模型选型与rerank阈值调优&#xff08;附实测Benchmark数据&#xff09; 技术文档检索失败常源于文本切分不合理、语义表征能力不足或重排…...

Linux新手看过来:手把手解决TeXLive安装与VSCode配置中的那些“坑”(从镜像下载到环境变量)

Linux新手避坑指南&#xff1a;TeXLive安装与VSCode配置全流程解析 第一次在Linux系统上配置TeXLive和VSCode环境时&#xff0c;我花了整整两天时间才把所有问题解决。那些看似简单的教程在实际操作中总会遇到各种意外情况——镜像下载速度慢如蜗牛、环境变量配置错误导致命令无…...