【高阶数据结构】并查集

并查集

  • 并查集
    • 1、概念
    • 2、根据人找编号 / 根据编号找人(简单介绍一下并查集)
      • (1)代码展示
      • (2)调试结果
      • (3)优化1:小的往大的合并
      • (4)优化2:压缩路径
    • 3、并查集操作和演示题目
      • (1)并查集操作
        • i、思路
        • ii、总体代码
      • (2)演示题目:省份数量
        • i、做法一:自己写一个并查集
        • ii、做法二:手动版本
      • (3)演示题目:等式方程可满足性


并查集

1、概念

并查集(Union-Find)是一种可以用来判断同属一个集合中相互关联的元素属于几个集合,也可以用来判断图结构中的两点是否是连通, 它也是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。

2、根据人找编号 / 根据编号找人(简单介绍一下并查集)

(1)代码展示

// UnionFindSet.h
#pragma once#include <vector>
#include <map>template <class T>
class UnionFindSet
{
private:std::vector<T> _a;			// 编号找人std::map<T, int> _indexmap; // 人找编号的映射关系
public:UnionFindSet(const T* a, size_t n){for (size_t i = 0; i < n; i++){_a.push_back(a[i]);  // 将传进来的值存入到vector中_indexmap[a[i]] = i; // 映射关系}}
};
// photo.cpp
#include <iostream>
#include "UnionFindSet.h"int main()
{std::string s[] = { "张三", "李四", "王五", "赵六" };UnionFindSet<std::string> ufs(s, 4);return 0;
}

(2)调试结果

在这里插入图片描述

(3)优化1:小的往大的合并

在这里插入图片描述

(4)优化2:压缩路径

	// 找根int FindRoot(int x){int root = x;while (_ufs[root] >= 0){root = _ufs[root]; // 下标和值的关系}// 压缩路径while (_ufs[x] >= 0){int parent = _ufs[x]; // 提前存一下父亲结点的值_ufs[x] = root; // 往上找x = parent;}return root;}

在这里插入图片描述

3、并查集操作和演示题目

(1)并查集操作

i、思路

在这里插入图片描述
在这里插入图片描述

ii、总体代码
class UnionFindSet
{
private:std::vector<int> _ufs;
public:UnionFindSet(size_t n): _ufs(n, -1){}// 合并void Union(int x1, int x2){int root1 = FindRoot(x1);int root2 = FindRoot(x2);// 俩根在一颗树上if (root1 == root2) return;// 更新_ufs[root1] += _ufs[root2]; // 前面的值+=后面的值_ufs[root2] = root1; // 更新后面的值为前面的值(双亲根)}// 找根int FindRoot(int x){int parent = x;while (_ufs[parent] >= 0){parent = _ufs[parent]; // 下标和值的关系}return parent;}// 判断是否是同一个树bool IsSet(int x1, int x2){return FindRoot(x1) == FindRoot(x2);}// 算树的数量int Size(){int n = _ufs.size();int size = 0;for (int i = 0; i < n; i++){if (_ufs[i] < 0){size++;}}return size;}
};

(2)演示题目:省份数量

i、做法一:自己写一个并查集

leetcode题目链接跳转
在这里插入图片描述

class UnionFindSet
{
private:std::vector<int> _ufs;
public:UnionFindSet(size_t n): _ufs(n, -1){}// 合并void Union(int x1, int x2){int root1 = FindRoot(x1);int root2 = FindRoot(x2);// 俩根在一颗树上if (root1 == root2) return;// 更新_ufs[root1] += _ufs[root2]; // 前面的值+=后面的值_ufs[root2] = root1; // 更新后面的值为前面的值(双亲根)}// 找根int FindRoot(int x){int parent = x;while (_ufs[parent] >= 0){parent = _ufs[parent]; // 下标和值的关系}return parent;}// 判断是否是同一个树bool IsSet(int x1, int x2){return FindRoot(x1) == FindRoot(x2);}// 算树的数量int Size(){int n = _ufs.size();int size = 0;for (int i = 0; i < n; i++){if (_ufs[i] < 0){size++;}}return size;}
};
class Solution 
{
public:int findCircleNum(vector<vector<int>>& isConnected) {UnionFindSet ufs(isConnected.size());for (int i = 0; i < isConnected.size(); i++){for (int j = 0; j < isConnected[i].size(); j++){if (isConnected[i][j] == 1){ufs.Union(i, j);}}}return ufs.Size();}
};
ii、做法二:手动版本
class Solution 
{
public:int findCircleNum(vector<vector<int>>& isConnected) {vector<int> ufs(isConnected.size(), -1);// lambda表达式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);int root2 = FindRoot(j);if (root1 != root2){ufs[root1] += ufs[root2];ufs[root2] = root1;}}}}int n = 0;for (auto e : ufs){if (e < 0)n++;}return n;}
};

(3)演示题目:等式方程可满足性

leetcode题目链接跳转

在这里插入图片描述
进行两次遍历,第一次遍历假如说是中间是等号的情况下的话,就将俩字母都放到同一个集合中,第二次遍历假如说是中间是不等号的情况下的话,就判断俩字母是否是在同一个集合中,在的话就返回false,不在的话就返回true。

class Solution 
{
public:bool equationsPossible(vector<string>& equations) {vector<int> ufs(26, -1);// lambda表达式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');int root2 = FindRoot(str[3] - 'a');if (root1 != root2){ufs[root1] += ufs[root2];ufs[root2] = root1;}}}// 第二遍遍历,遇到相同的俩字母在一个集合中就返回falsefor (auto& str : equations){if (str[1] == '!'){int root1 = FindRoot(str[0] - 'a');int root2 = FindRoot(str[3] - 'a');if (root1 == root2){return false;}}}return true;}
};

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

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

相关文章

Linux下安装gmp6.2.1的详细操作(深度学习)

方式一&#xff1a;编译gmp GMP官方地址https://gmplib.org/ 1. 官网下载gmp安装包 2. 解压下载好的安装包 tar -zxvf gmp-6.2.1.tar.bz2 3. 进入解压后的文件夹 cd gmp-6.2.1 4. 指定安装路径进行安装 # /usr/local换成自己的安装路径 ./configure --prefix/usr/local 5. 编…

鸿蒙ArkUI-X跨平台开发电商应用

一、ArkUI-X 简介 ArkUI-X 是由 OpenHarmony TSC - 跨平台应用开发框架 TSG 所孵化的开源项目,使用ArkUI-X可以让开发者基于一套主代码, 就可以构建支持多平台的精美、高性能应用。目前支持OpenHarmony、HarmonyOS、Android、 iOS,后续会逐步增加更多平台支持。 ArKUI跨平台…

volatile 和 synchronzied 的区别

文章目录 概述volatilesynchornizedvolatile vs synchornized总结 概述 提起并发编程&#xff0c;我们不得不说起 volatile 和 synchronized 这两个关键字&#xff0c;这两个关键字也是面试中常常被问到的&#xff0c;下面我们分别介绍一下这两个关键字以及二者的异同。首先需要…

Java构造方法详解

在Java方法内部定义一个局部变量时&#xff0c;必须要初始化&#xff0c;否则就会编译失败&#xff0c;如下&#xff1a; 要让上述代码通过编译&#xff0c;只需在使用a之前给a赋一个初始值即可 如果是对象&#xff1a;下面用一个日期类演示 我们没有给年月日赋值&#xff0c;…

[通用人工智能] 论文分享:ElasticViT:基于冲突感知超网的快速视觉Transformer

引言: 近年来&#xff0c;视觉Transformer&#xff08;Vision Transformer&#xff0c;简称ViT&#xff09;在计算机视觉任务中的应用日益广泛&#xff0c;从图像分类到对象识别等&#xff0c;均显示出优越的性能。然而&#xff0c;ViT模型也面临一些挑战&#xff0c;特别是在模…

ASME美国机械工程师学会文献如何查询下载经验分享

一、ASME美国机械工程师学会数据库简介&#xff1a; ASME是世界上最大的技术出版机构之一&#xff0c;制定众多的工业和制造业行业标准。现在ASME拥有工业和制造行业的600项标准和规范&#xff0c;这些标准在全球90多个国家被采用。 ASME数据库包含25种专业期刊&#xff0c;其…

鸿蒙内核源码分析(共享内存) | 进程间最快通讯方式

运行机制 共享好端端的一词&#xff0c;近些年被玩坏了&#xff0c;共享单车,共享充电宝,共享办公室&#xff0c;共享雨伞… 甚至还有共享女朋友&#xff0c;真是人有多大胆&#xff0c;共享有多大产。但凡事太尽就容易恶心到人&#xff0c;自己也一度被 共享内存 恶心到了&am…

OpenHarmony 实战开发——轻量带屏解决方案之恒玄芯片移植案例

本文章基于恒玄科技BES2600W芯片的欧智通 Multi-modal V200Z-R开发板 &#xff0c;进行轻量带屏开发板的标准移植&#xff0c;开发了智能开关面板样例&#xff0c;同时实现了ace_engine_lite、arkui_ui_lite、aafwk_lite、appexecfwk_lite、HDF等部件基于OpenHarmony LiteOS-M内…

论文AI率:检测原理是什么?该如何降低论文AI率?

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 上一篇介绍了10个检测AI率的在线工具。本篇来说说AI率到底是如何检测出来的&#xff1f;该如何有效降低论文的AI率&#xff1f; 和AI大模型一样&#xff0c;AI检测的核心也是…

vscode打开esp-idf工程,找不到头文件,有波浪线

就像这样 多半是因为原始的工程不是用vscode的插件新建的&#xff0c;因此没有相关的路径。需要在工程文件夹下的.vscode文件夹中的c_cpp_properties.json文件中增加路径&#xff0c;可以参考插件自动新建的工程里面的写法 {"configurations": [{"name":…

线上问题——一次几经反转惊心动魄的问题排查记录

背景简述 线上某业务由于查询大量数据频繁FullGc优化&#xff0c;依赖于用户完课进度&#xff0c;测试时需要造大量的用户和专栏内容发放数据&#xff0c;且需要用户完课触发&#xff0c;因此在FAT造了一个5000人的班级&#xff0c;这个班级只有3个课时&#xff0c;测试通过脚…

Midjourney与Stable Diffusion大比拼:AI绘画技术的未来

在当今快速发展的人工智能技术浪潮中&#xff0c;AI绘画软件成为了艺术和技术交汇的新领域。两大巨头——Midjourney和Stable Diffusion&#xff0c;在这一领域中引领风骚&#xff0c;它们以其独特的功能和强大的生成能力&#xff0c;让创作者能够将想象力化为现实。本文将深入…

进程与线程含义、区别及在操作系统中的意义(简要)

在现代操作系统中&#xff0c;进程和线程是构建多任务环境的基础。它们虽然紧密相关&#xff0c;但各自扮演着不同的角色。本文将深入探讨进程与线程的概念、它们之间的区别&#xff0c;以及为什么操作系统中会存在进程这一概念。 进程&#xff1a;独立运行的实体 它是操作系…

conan2 基础入门(04)-指定编译器(gcc为例)

conan2 基础入门(04)-指定编译器(gcc为例) 文章目录 conan2 基础入门(04)-指定编译器(gcc为例)⭐准备生成profile文件预备文件和Code ⭐使用指令预览正确执行结果可能出现的问题 ⭐具体讲解conancmake ENDsettings.yml ⭐准备 生成profile文件 # 生成默认profile文件&#xf…

国产操作系统下Chrome的命令行使用 _ 统信 _ 麒麟

原文链接&#xff1a;国产操作系统下Chrome的命令行使用 | 统信 | 麒麟 Hello&#xff0c;大家好啊&#xff01;今天我们来聊聊如何在国产操作系统上使用命令行操作Google Chrome。无论是进行自动化测试、网页截图还是网页数据抓取&#xff0c;使用命令行操作Google Chrome都能…

Go编程语言的调试器Delve | Goland远程连接Linux开发调试(go远程开发)

文章目录 Go编程语言的调试器一、什么是Delve二、delve 安装安装报错cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in $PATH解决 三、delve命令行使用delve 常见的调试模式常用调试方法todo调试程序代码与动态库加载程序运行…

常用的简单友好的工单系统(免费)- WGCAT

最近在项目中&#xff0c;有工单系统的需求场景&#xff0c;所以想寻找一款轻量简单的运维工单软件&#xff0c;主要用来记录和处理工作中的一些故障、维护&#xff0c;主要用来记录设备的维护状态&#xff0c;包括服务器、主机、交换机那些 WGCAT&#xff0c;是一款简单轻量的…

知从科技战略客户经理张志强受邀出席2024 AutoSec中国汽车网络安全与数据安全峰会

4月11-12日&#xff0c;AutoSec8周年年会暨中国汽车网络安全及数据安全合规峰会在上海成功举办。此次峰会吸引了来自全球各地的头部汽车网络安全企业、OEM厂商、安全专家和学者等齐聚盛会&#xff0c;零距离共话智能网联汽车产业的新发展、新趋势。 知从科技董事长成云霞亲自带…

mapreduce | 自定义Partition分区(案例1)

1.需求 将学生成绩&#xff0c;按照各个成绩降序排序&#xff0c;各个科目成绩单独输出。 # 自定义partition 将下面数据分区处理&#xff1a; 人名 科目 成绩 张三 语文 10 李四 数学 30 王五 语文 20 赵6 英语 40 张三 数据 50 李四 语文 10 张三 英语 70 李四 英语…

MapReduce | 二次排序

1.需求 主播数据--按照观众人数降序排序&#xff0c;如果观众人数相同&#xff0c;按照直播时长降序 # 案例数据 用户id 观众人数 直播时长 团团 300 1000 小黑 200 2000 哦吼 400 7000 卢本伟 100 6000 八戒 250 5000 悟空 100 4000 唐僧 100 3000 # 期望结果 哦吼 4…