并查集实现|并查集在相关题目中的应用|手撕数据结构专栏

news/2024/7/5 2:03:03

前言

那么这里博主先安利一下一些干货满满的专栏啦!

高质量干货博客汇总icon-default.png?t=N7T8http://t.csdnimg.cn/jdQXqGit企业开发控制理论和实操icon-default.png?t=N7T8http://t.csdnimg.cn/PyPJeDocker从认识到实践再到底层原理icon-default.png?t=N7T8http://t.csdnimg.cn/G6Inp手撕数据结构icon-default.png?t=N7T8http://t.csdnimg.cn/XeyJn


这里是很多数据结构的模拟实现源码,都是我自己编写的仿照stl风格的数据结构模拟实现。

GitHub - Yufccode/CPlusPlus-review-main: 这是我复习C++的时候所用的一些代码和文件这是我复习C++的时候所用的一些代码和文件. Contribute to Yufccode/CPlusPlus-review-main development by creating an account on GitHub.icon-default.png?t=N7T8https://github.com/Yufccode/CPlusPlus-review-main


并查集

并查集的表示

1. 像堆类似,用下标表示关系

2. 双亲表示法

一开始数组存的是-1,表示每个数都是一棵树,每个数表示一个集合

假设数组:

int a = [-1,-1,-1,-1,-1];

这个数组进行一次合并之后变成:

int a = [-1,0,-1,-1,-1];

这个表示下标为1的数的父亲就是下标为0的数。

如果下标为负数,那么这个数就是树的根。

合并

找根,只能是根的合并。

谁合并谁没有严格的要求(压缩路径才需要要求,一般性能要求比较高才需要压缩路径)。

并查集实现

template <class T>
class union_find_disjoint_set
{
private:
    std::vector<T> __ufs; // 通过编号找人
public:
    union_find_disjoint_set(size_t n)
        : __ufs(n, -1) {} // 先初始化成-1
    void Union(int x1, int x2)
    {
        int root1 = FindRoot(x1);
        int root2 = FindRoot(x2);
        if (root1 == root2) // 如果在一个集合就没必要合并了
            return;
        if (root1 > root2)
            std::swap(root1, root2); // 统一让下标小的根去合并大的根,其实这个是没有要求的
        __ufs[root1] += __ufs[root2];
        __ufs[root2] = root1;
    }
    int FindRoot(int x)
    {
        int root = x;
        while (__ufs[root] >= 0)
            root = __ufs[root];
        return root;
    }
    bool InSet(int x1, int x2) // 判断是否在同一个集合
    {
        return FindRoot(x1) == FindRoot(x2);
    }
    size_t SetSize()
    {
        size_t cnt = 0;
        for (const auto &e : __ufs)
            if (e < 0)
                ++size;
        return size;
    }
};

相关题目

547. 省份数量

https://leetcode.cn/problems/number-of-provinces/description/icon-default.png?t=N7T8https://leetcode.cn/problems/number-of-provinces/description/把并查集复制进去。这样调用即可。

class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        union_find_disjoint_set<int> ufs(isConnected.size());
        for(size_t i = 0; i<isConnected.size(); i++)
        {
            for(size_t j = 0; j < isConnected[i].size(); j++)
            {
                if(isConnected[i][j] == 1)
                {
                    ufs.Union(i, j);
                }
            }
        }
        // 现在所有城市能合并的已经合并完了
        return ufs.SetSize();
    }
};

990. 等式方程的可满足性

class Solution {
public:
    bool equationsPossible(vector<string>& equations) {
        std::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');
                int root2 = findroot(str[3] - 'a');
                if(root1 != root2)
                {
                    ufs[root1] += ufs[root2];
                    ufs[root2] = root1;
                }
            }
        }
        // 第二遍,看看不相等的是否会出现在一个集合中
        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://lihuaxi.xjx100.cn/news/2015025.html

相关文章

SQLSERVER tempdb 数据库异常增大解决方法及原因查找

--SQLSERVER tempdb 数据库异常增大&#xff0c;导致服务器卡顿&#xff0c;最简单的方法就是重启系统.tempdb 会自动重新创建恢复到初始大小(比如8M). --1.tempdb 文件过大&#xff0c;可以通过重新启动系统&#xff0c;tempdb数据文件及Log会释放空间到初始大小(比如8M). …

Kafka 使用手册

kafka3.0 文章目录 kafka3.01. 什么是kafka&#xff1f;2. kafka基础架构3. kafka集群搭建4. kafka命令行操作主题命令行【topic】生产者命令行【producer】消费者命令行【consumer】 5. kafka生产者生产者消息发送流程Producer 发送原理普通的异步发送带回调函数的异步发送同步…

【Docker】了解Docker Desktop桌面应用程序,TA是如何管理和运行Docker容器(2)

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Docker容器》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…

【excel密码】Excel加密的三种方式

Excel中保存着重要的数据&#xff0c;想要保护数据源&#xff0c;我们会想到给Excel文件进行加密&#xff0c;方法有很多&#xff0c;今天分享三种Excel加密方法给大家。 打开密码 设置了打开密码的excel文件&#xff0c;打开文件就会提示输入密码才能打开excel文件&#xff…

如何区分流量控制和拥塞控制?

流量控制属于通信双方协商&#xff1b;拥塞控制涉及通信链路全局。 流量控制需要通信双方各维护一个发送窗、一个接收窗&#xff0c;对任意一方&#xff0c;接收窗大小由自身决定&#xff0c;发送窗大小由接收方响应的TCP报文段中窗口值确定&#xff1b;拥塞控制的拥塞窗口大小…

代码审计-CVE-2023-6654-PHPEMS-加密-解密分析

路由&#xff1a; 入口方法&#xff1a; 鉴权分析&#xff1a; 由此可以得出 鉴权是由session类负责获取参数后&#xff0c;由各个类的魔术方法负责&#xff1a;&#xff08;在此还有一个方法 全局搜索登录关键词&#xff09; 1、断点分析&#xff1a; 寻找鉴权点分析&#…

Netty核心原理与基础实战(二)——详解Bootstrap 备份

接上篇&#xff1a;Netty核心原理与基础实战&#xff08;一&#xff09; 1 Bootstrap基础概念 Bootstrap类是Netty提供的一个便利的工厂类&#xff0c;可以通过它来完成Netty的客户端或服务端的Netty组件的组装&#xff0c;以及Netty程序的初始化和启动执行。Netty的官方解释是…

环境配置:Ubuntu18.04 ROS Melodic安装

前言 不同版本的Ubuntu与ROS存在对应关系。 ROS作为目前最受欢迎的机器人操作系统&#xff0c;其核心代码采用C编写&#xff0c;并以BSD许可发布。ROS起源于2007年&#xff0c;是由斯坦福大学与机器人技术公司Willow Garage合作的Switchyard项目。2012年&#xff0c;ROS团队从…