【高阶数据结构】并查集

并查集

  • 并查集
    • 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;下面我们分别介绍一下这两个关键字以及二者的异同。首先需要…

3099.哈沙德数——力扣

3099. 哈沙德数 已解答 简单 相关标签 相关企业 提示 如果一个整数能够被其各个数位上的数字之和整除&#xff0c;则称之为 哈沙德数&#xff08;Harshad number&#xff09;。给你一个整数 x 。如果 x 是 哈沙德数 &#xff0c;则返回 x 各个数位上的数字之和&#xff0…

Java构造方法详解

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

RIP、OSPF、BGP等协议及华为路由器配置总结

直连路由&#xff1a;无需配置&#xff0c;当接口存在IP且状态正常时&#xff0c;路由器会自动生成直连网段的路由表。&#xff08;*可以配置自身作为下一跳&#xff09; 对于不直连的网段&#xff0c;需要静态路由&#xff08;手动配置、适合简单拓扑&#xff09;或动态路由&…

[通用人工智能] 论文分享: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;其…

Java数据结构(链表实战一)

前言 基于链表的操作比较多&#xff0c;希望通过一系列的实战操作&#xff0c;加深对链表的理解和应用。每日更新两题&#xff0c;希望学习的小伙伴关注一波&#xff0c;评论区欢迎讨论交流。 今日份练习 打印两个有序链表的公共部分 实现原理 既然是有序链表&#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检测的核心也是…

软件设计师考试---一系列

直接内存存取 直接内存存取&#xff08;Direct Memory Access&#xff0c;简称DMA&#xff09;是计算机处理器中的一种特性&#xff0c;它允许外部存储器&#xff08;例如硬盘或网络适配器&#xff09;在不需要中央处理器的干预下直接访问计算机的内存空间。这种机制显著加快了…

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

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

布隆过滤器详解

什么是布隆过滤器 布隆过滤器&#xff08;Bloom Filter&#xff09;是一种空间效率极高的概率型数据结构&#xff0c;由伯顿布隆&#xff08;Burton Howard Bloom&#xff09;在1970年提出。它主要用于测试一个元素是否属于某个集合&#xff0c;尽管存在一定的误报率&#xff0…

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

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

RTEMS RPi4B BSP 添加system timer驱动支持

RPi4 有两种timer&#xff0c;ARM timer 和 system timer。 The ARM Timer is based on a ARM SP804, but it has a number of differences with the standard SP804. The clock from the ARM timer is derived from the system clock. This clock can change dynamically e.…

回溯算法1

回溯函数又称为递归函数&#xff0c;是纯暴力搜索。 回溯算法可以解决 组合问题&#xff0c;切割问题&#xff0c;子集问题&#xff0c;排列问题&#xff0c;棋盘问题&#xff08;n皇后&#xff09;。 在解决这些问题的时候可以使用n循环&#xff0c;但是十分困难&#xff0c…

如何在LangChain的agent中记录对话历史

在前两篇文章中&#xff0c;我分别实现了可以抓取并总结网页的agent和一个可以管理日程的agent&#xff0c;里面演示了基本agent创建和使用流程&#xff0c;也为agent添加了特殊的功能。但你仔细观察就会发现&#xff0c;我们的两个agent都是只支持单轮对话&#xff0c;也就是你…

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

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