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

并查集-547.省份的数量-力扣(LeetCode)

个人主页:1白天的黑夜1-CSDN博客

专栏:力扣刷题录_1白天的黑夜1的博客-CSDN博客、企鹅程序员:Linux 系统与网络编程_1白天的黑夜1的博客-CSDN博客

目录

一、题目解析

1、省份是一组直接或间接相连的城市(没有链接的单独城市也是省份)

2、isConnected[i][j]== 1 or 0,并且isConnected[i][j] == isConnected[j][i]

二、算法原理

解法1:自己造轮子(写一个并查集出来)

具体步骤:

1、将自己写好的并查集直接复制粘贴过来

2、通过size()获取城市的数目初始化并查集父指针数组,通过并查集构造函数

3、遍历二维数组isConnected

3.1、如果isConnected[i][j] == 1,通过Uoion()合并函数,合并i和j;如果遇到isConnected[j][i] == 1,在Union()函数内会判断i和j的根是否相同,相等则不会合并。

3.2、如果isConnected[i][j] ==0,循环继续

4、循环结束后,通过SetSize()返回并查集中的集合个数,也就是省份的个数

解法2:通过lambda函数实现核心合并功能

具体步骤:

1、创建一个vector数组用于充当父指针数组,通过vector构造函数全部初始化为-1

2、将找根函数,用lambda表达式实现一个简单的匿名函数

3、遍历isConnected二维数组

3.1、如果isConnected[i][j] == 1,则说明可以开始合并了,但还需判断根是否相同

3.2、通过lambda表达式实现的找根匿名函数找到i和j的根,如果不相等,则合并,将其中合并根父指针数组存的值+=被合并根的父指针数组存的值,并将被合并根的父指针数组的值修改为合并的根(这里就是合并的主逻辑)

3.3、如果isConnected[i][j] == 0,则循环继续

4、在并查集中,如果是根,其值为负数,所以遍历一遍创建的vecter的数组,统计省份的数量

依据算法原理或者你自己想的解法,各位读者可以去尝试一番,提升自己的代码能力

三、代码示例

解法1:

解法2:

看到最后,如果对您有所帮助,还请点赞、收藏和关注一键三连,在未来还会继续带来优秀的内容,感谢观看,我们下期再见!


一、题目解析

1、省份是一组直接或间接相连的城市(没有链接的单独城市也是省份)

2、isConnected[i][j]== 1 or 0,并且isConnected[i][j] == isConnected[j][i]

二、算法原理

若读者对并查集比较陌生,或者有点遗忘了,可以移步博主的博客去学习或回顾一下

高阶数据结构-并查集-CSDN博客

解法1:自己造轮子(写一个并查集出来)

我们可以发现,将两个城市连接起来,是不是有点类似我们并查集的合并,而最终返回的省份个数就相当于我们查询并查集中有多少个集合。

具体步骤:

1、将自己写好的并查集直接复制粘贴过来

2、通过size()获取城市的数目初始化并查集父指针数组,通过并查集构造函数

3、遍历二维数组isConnected

3.1、如果isConnected[i][j] == 1,通过Uoion()合并函数,合并i和j;如果遇到isConnected[j][i] == 1,在Union()函数内会判断i和j的根是否相同,相等则不会合并。
3.2、如果isConnected[i][j] ==0,循环继续

4、循环结束后,通过SetSize()返回并查集中的集合个数,也就是省份的个数

解法2:通过lambda函数实现核心合并功能

如果我们以后遇到了类似的题也能直接粘贴我们自己造的轮子(并查集)吗?这肯定是不现实的,在经过并查集的学习后,我们掌握了其基本理念,结合我们所学的lambda表达式,我们也能解决该题。

具体步骤:

1、创建一个vector数组用于充当父指针数组,通过vector构造函数全部初始化为-1

2、将找根函数,用lambda表达式实现一个简单的匿名函数

Lambda表达式是C++11引入的一种简便方法,用于在被调用的位置或作为参数传递给函数的位置定义匿名函数对象(闭包)。它的基本语法如下:

[capture list] (parameter list) -> return type { function body }

其中:

  • capture list 是捕获列表,用于指定Lambda表达式可以访问的外部变量,以及是按值还是按引用的方式访问。

  • parameter list 是参数列表,用于表示Lambda表达式的参数,可以为空,也可以指定参数的类型和名称。

  • return type 是返回值类型,可以省略,由编译器根据函数体推导。

  • function body 是函数体,用于表示Lambda表达式的具体逻辑。

捕获方式

Lambda表达式支持多种捕获方式:

  • 值捕获:在捕获列表中使用变量名,表示将该变量的值拷贝到Lambda表达式中。

  • 引用捕获:在捕获列表中使用&加变量名,表示将该变量的引用传递到Lambda表达式中。

  • 隐式捕获:在捕获列表中使用=或&,表示按值或按引用捕获Lambda表达式中使用的所有外部变量。

  • 初始化捕获:C++14引入的一种新的捕获方式,允许在捕获列表中使用初始化表达式。

3、遍历isConnected二维数组

3.1、如果isConnected[i][j] == 1,则说明可以开始合并了,但还需判断根是否相同
3.2、通过lambda表达式实现的找根匿名函数找到i和j的根,如果不相等,则合并,将其中合并根父指针数组存的值+=被合并根的父指针数组存的值,并将被合并根的父指针数组的值修改为合并的根(这里就是合并的主逻辑)
3.3、如果isConnected[i][j] == 0,则循环继续

4、在并查集中,如果是根,其值为负数,所以遍历一遍创建的vecter的数组,统计省份的数量

依据算法原理或者你自己想的解法,各位读者可以去尝试一番,提升自己的代码能力

547. 省份数量 - 力扣(LeetCode)

三、代码示例

解法1:

class UnionFindSet
{
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;//小的做根if (root1 > root2) swap(root1, root2);_ufs[root1] += _ufs[root2];_ufs[root2] = root1;}int FindRoot(int x)//找根{int parent = x;while (_ufs[parent] >= 0){parent = _ufs[parent];}return parent;}bool InSet(int x1,int x2){ return FindRoot(x1) == FindRoot(x2);}size_t SetSize(){size_t size = 0;for (size_t i = 0; i < _ufs.size(); i++){if (_ufs[i] < 0) ++size;}return size;}private:vector<int> _ufs;
};
//解法1:通过并查集
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]){ufs.Union(i,j);}}}return ufs.SetSize();}
};

解法2:

//解法2:写一个findroot的lambda表达式
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]){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;}
};

看到最后,如果对您有所帮助,还请点赞、收藏和关注一键三连,在未来还会继续带来优秀的内容,感谢观看,我们下期再见!

http://www.dtcms.com/a/486112.html

相关文章:

  • 生命周期全景图:从componentDidMount到getSnapshotBeforeUpdate
  • p2p做网站plc编程入门基础知识
  • 学院个人信息|基于SprinBoot+vue的学院个人信息管理系统(源码+数据库+文档)
  • Unity AB包加载与依赖管理全解析
  • 基于Springboot的游戏网站的设计与实现45nuv3l8(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 深入理解 Vue.js 原理
  • 基于bert-base-chinese的外卖评论情绪分类项目
  • OpenSSL EVP编程介绍
  • 网站服务器组建中国国际贸易网站
  • 上新!功夫系列高通量DPU卡 CONFLUX®-2200P 全新升级,带宽升 40% IOPS提60%,赋能多业务场景。
  • Spring Boot 3零基础教程,properties文件中配置和类的属性绑定,笔记14
  • 以数据智能重构 OTC 连锁增长逻辑,覆盖网络与合作生态双维赛跑
  • 【推荐100个unity插件】基于节点的程序化无限地图生成器 —— MapMagic 2
  • 71_基于深度学习的布料瑕疵检测识别系统(yolo11、yolov8、yolov5+UI界面+Python项目源码+模型+标注好的数据集)
  • 工控机做网站服务器网络模块
  • Mac——文件夹压缩的简便方法
  • Playwright自动化实战一
  • 电商网站开发面临的技术问题做seo网站诊断书怎么做
  • 【Qt】QTableWidget 自定义排序功能实现
  • WPF 疑点汇总2.HorizontalAlignment和 HorizontalContentAlignment
  • 【Qt】3.认识 Qt Creator 界面
  • 垂直网站建设付费小说网站怎么做
  • PDFBox - PDDocument 与 byte 数组、PDF 加密
  • 【Pytorch】分类问题交叉熵
  • 如何轻松删除 realme 手机中的联系人
  • Altium Designer怎么制作自己的集成库?AD如何制作自己的原理图库和封装库并打包生成库文件?AD集成库制作好后如何使用丨AD集成库使用方法
  • Jackson是什么
  • 代码实例:Python 爬虫抓取与解析 JSON 数据
  • 襄阳建设网站首页百度知识营销
  • 山东住房和城乡建设厅网站电话开发软件都有哪些