【高阶数据结构】并查集

并查集

  • 并查集
    • 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;
                }
            }
        }
        // 第二遍遍历,遇到相同的俩字母在一个集合中就返回false
        for (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.mfbz.cn/a/605807.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker-compose安装es+kibana 8.12.2

小伙伴们&#xff0c;你们好&#xff0c;我是老寇&#xff0c;我又回来辣&#xff0c;几个月不见甚是想念啊&#xff01;&#xff01;&#xff01; 因云平台需要改造&#xff0c;es7升级为es8&#xff0c;所以记录一下&#xff0c;es8需要开启ssl认证&#xff0c;需要配置证书…

AC/DC电源模块在通信与网络设备中的应用研究

BOSHIDA AC/DC电源模块在通信与网络设备中的应用研究 随着通信与网络技术的不断发展&#xff0c;通信与网络设备的使用不断增加。电源作为通信与网络设备的重要组成部分之一&#xff0c;在其稳定工作中起到至关重要的作用。AC/DC电源模块作为一种常用的电源转换器&#xff0c;…

探索设计模式的魅力:权力集中,效率提升,中心化模式的优势与挑战

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索中心化模式之旅✨ 大家好啊&#xff01;&#x1f44b; 这次我们要聊的是IT界一…

使用js/java合并3dtiles

目录 前言&#xff1a; 需合并的json目录 aa/tileset.json bb/tileset.json cc/tileset.json dd/tileset.json ee/tileset.json js源码&#xff1a; 运行命令&#xff1a; 生成结果&#xff1a; java源码&#xff1a; Matrix.java ThreeDTilesJoin2.java pom文件…

【中级软件设计师】上午题15-计算机网络

上午题15-计算机网络 1 网络设备2 协议簇3 TCP和UDP4 SMTP和POP35 ARP和RARP6 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;7 URL8 浏览器9 IP地址和子网划分10 IPv611 Windows命令12 路由器 1 网络设备 物理层设备&#xff1a;中继器、集线器&#xff0…

目标检测正负样本区分和平衡

1、正负样本定义 rpn和rcnn的正负样本定义都是基于MaxIoUAssigner&#xff0c;只不过定义阈值不一样而已。 MaxIoUAssigner的操作包括4个步骤&#xff1a; 首先初始化时候假设每个anchor的mask都是-1&#xff0c;表示都是忽略anchor 将每个anchor和所有gt的iou的最大Iou小于…

C# SolidWorks 二次开发 -从零开始创建一个插件(3) 发布插件

五一节过完了吧&#xff0c;该上班学习了吧&#xff1f; 如何把自己开发好的程序优雅的给别人使用。 今天我们来简单讲解一下&#xff0c;这个之前不少粉丝咨询过相关问题&#xff0c;自己开发好的东西&#xff0c;如何给同事或者其它人使用。 先列一下使用到的主要工具&am…

什么是存量与流量?

存量与流量是反映经济状况的两类指标&#xff0c;在统计和国民经济核算中得到广泛运用。存量与流量之间既有密切的联系&#xff0c;又有一定区别。 一、存量与流量的基本概念 存量是某一时点结存的量&#xff0c;体现了某一时点上持有的经济价值或物量&#xff1b;流量是一段…

基于YOLO的车牌与车型识别系统

一、项目背景与意义 随着智能交通系统的快速发展&#xff0c;车辆识别技术在交通管理、安防监控、自动收费、停车管理等领域发挥着至关重要的作用。车牌识别和车型识别作为车辆识别技术的核心组成部分&#xff0c;能够有效提升交通运营效率&#xff0c;加强公共安全监控&#…

阿里云发布通义千问2.5,OpenCompass上得分追平GPT-4 Turbo

5月9日消息&#xff0c;阿里云正式发布通义千问2.5&#xff0c;模型性能全面赶超GPT-4 Turbo&#xff0c;成为地表最强中文大模型。同时&#xff0c;通义千问最新开源的1100亿参数模型在多个基准测评收获最佳成绩&#xff0c;超越Meta的Llama-3-70B&#xff0c;成为开源领域最强…

Davinci工程CANTP模块讲解

配置CAN的TP模式&#xff0c;涉及BSW\CanTp\CanTp.c和CanTp.h CanTpChannels 他有两组收发&#xff0c;功能诊断和物理诊断。 功能诊断有自己的参数要求 物理诊断的接收要求相对多一些 由于发送只有一个&#xff0c;所以我们把它放在物理诊断接收那组里面。 CanTpGeneral 也…

关于在阿拉伯语中占位符出现的问题

项目中用到了阿语的翻译&#xff0c;本来是直接复制过来就行&#xff0c;但是在一个使用到占位符的地方出现了问题 这是正常的内容但是粘贴到studio后却不是这样的 变成这样了那个逗号一样的文字的位置变了&#xff0c;这样一来占位符彻底无法用了还会报错。 经过多方尝试和群…

学习Uni-app开发小程序Day3

经过五一长假&#xff0c;回过头在去看学习的东西&#xff0c;发现仍然是一筹莫展的&#xff0c;看来&#xff0c;学习是不能松懈的&#xff0c;得&#xff0c;自己在把以前的从头复习一遍&#xff0c;加深印象。今天在继续听课&#xff0c;但是出现一个问题&#xff0c;是黑码…

大家都是怎么写毕业论文的? 推荐4个AI工具

写作这件事一直让我们从小学时期就开始头痛&#xff0c;初高中时期800字的作文让我们焦头烂额&#xff0c;一篇作文里用尽了口水话&#xff0c;拼拼凑凑才勉强完成。 大学时期以为可以轻松顺利毕业&#xff0c;结果毕业前的最后一道坎拦住我们的是毕业论文&#xff0c;这玩意不…

FMEA如何在设计活动中有效应用?——FMEA软件

免费试用FMEA软件-免费版-SunFMEA 在现代产品设计和开发过程中&#xff0c;FMEA&#xff08;失效模式与影响分析&#xff09;已经成为了一种不可或缺的工具。它的核心目标是在产品或过程设计的早期阶段&#xff0c;通过识别和分析潜在的失效模式&#xff0c;预防和控制可能出现…

汽车软件研发工具链丨怿星科技新产品重磅发布

“创新引领未来”聚焦汽车软件新基建&#xff0c;4月27日下午&#xff0c;怿星科技2024新产品发布会在北京圆满举行&#xff01;智能汽车领域的企业代表、知名大企业负责人、投资机构代表、研究机构代表齐聚现场&#xff0c;线上直播同步开启&#xff0c;共同见证怿星科技从单点…

用一只小猪来解释 On-Prem, IaaS, PaaS 和 SaaS 的区别

亚马逊云科技首席布道师 Jeff Barr 在推上发过一张图&#xff0c;用一只小猪&#x1f437;讲清了 On-Prem, IaaS, PaaS 和 SaaS 的区别。 虽然历史悠久&#xff0c;但图片内容一点也没有过时。 On-prem 本地部署 本地部署&#xff08;on-prem, 或 on-premise&#xff09;指将…

qwfgjk

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

IDEA设置 | 个性化设置

文章目录 IDEA设置总结IDEA自动生成序列化ID IDEA设置总结 本篇博客将专注于整理IDEA新UI界面的相关设置 IDEA自动生成序列化ID CtrlAltS快捷键打开设置界面 选择Editor→Inspections→JVM languages→Test frameworks&#xff0c;勾选上Serializable class without serialVe…

vxe-table 区域选取、复制粘贴功能,的基本使用

vxe-table区域选取、复制粘贴功能&#xff0c;的基本使用&#xff08;注&#xff1a;该功能仅支持企业版&#xff0c;这里仅供部分演示&#xff09; 1.鼠标区域选择功能&#xff1a; 参数说明&#xff1a; mouse-config.area 是否开启鼠标单元格区域选取 <template>&l…
最新文章