想要精通算法和SQL的成长之路 - 并查集的运用和案例(省份数量)
想要精通算法和SQL的成长之路 - 并查集的运用
- 前言
- 一. 并查集的使用和模板
- 1.1 初始化
- 1.2 find 查找函数
- 1.3 union 合并集合
- 1.4 connected 判断相连性
- 1.5 完整代码
- 二. 运用案例 - 省份数量
前言
想要精通算法和SQL的成长之路 - 系列导航
一. 并查集的使用和模板
先说一下并查集的相关知识点:
- 含义:并查集,用于维护一组不相交的集合,支持合并两个集合和查询某个元素所属的集合。
- 用途:解决图论、连通性问题和动态连通性等问题。
通俗一点,可以使用并查集的算法题目有哪些特征?
- 需要将
n
个不同的元素划分为不相交的集合。 - 开始的时候,每个元素自行成为一个集合,然后需要根据一定的顺序进行 合并。
- 同时还需要 查询 某个元素是否属于哪个集合。
因此并查集的基本操作可以包含两个:
- 合并:将两个不相交的集合合并成一个集合。(将其中一个集合的根节点连接到另一个集合的根节点上)
- 查找:根据某个元素,寻找到它所在集合的根节点。
1.1 初始化
首先我们考虑下,并查集里面需要有哪些数据结构:
- 需要一个
parent[]
数组,用来存储每个元素对应的根节点。 - 再来一个
rank[]
数组,代表以每个元素作为根节点,其所在集合的大小。即代表某个集合的深度。 - 再来一个
sum
字段,代表当前的集合个数。
public class UnionFind {/*** 表示节点i的父节点*/private int[] parent;/*** 表示以节点i为根节点的子树的深度,初始时每个节点的深度都为0*/private int[] rank;private int sum;public UnionFind(int n) {parent = new int[n];rank = new int[n];// 初始时每个节点的父节点都是它自己for (int i = 0; i < n; i++) {parent[i] = i;}sum = n;}
}
1.2 find 查找函数
特征:
- 入参:元素
x
。 - 要做的事情:不断地向上递归寻找这个
x
的根节点。 - 递归终止条件:找到根节点。(根节点和元素本身一致)
代码如下:
public int find(int x) {while (x != parent[x]) {x = parent[x];}return x;
}
1.3 union 合并集合
特征:
- 入参:元素
x
和y
。 - 要做的事情:分别找到这两个元素的根节点:
rootX
和rootY
。 - 如果俩元素的根节点是同一个,说明他们在一个集合当中,不需要任何操作。
- 倘若两个元素的根节点不一样,根据两个集合的深度来判断。将深度小的那个集合,合并到深度大的集合中。同时更新对应的根节点和深度大小。
除此之外,我们还可以写一个简单的函数,用来判断两个元素是否处于同一个集合当中(或者是是否相连)
public void union(int x, int y) {int rootX = find(x);int rootY = find(y);// 如果两个元素的根节点一致,不需要合并if (rootX == rootY) {return;}// 如果根节点 rootX 的深度 > rootY。if (rank[rootX] > rank[rootY]) {// 那么将以rootY作为根节点的集合加入到rootX对应的集合当中rank[rootX] += rank[rootY];// 同时改变rootY的根节点,指向rootX。parent[rootY] = rootX;} else {// 反之rank[rootY] += rank[rootX];parent[rootX] = rootY;}
}
1.4 connected 判断相连性
/*** 判断两个节点是否在同一个集合中
*/
public boolean connected(int x, int y) {return find(x) == find(y);
}
1.5 完整代码
/*** @author Zong0915* @date 2023/10/4 下午2:52*/
public class UnionFind {/*** 表示节点i的父节点*/private int[] parent;/*** 表示以节点i为根节点的子树的深度,初始时每个节点的深度都为0*/private int[] rank;private int sum;public UnionFind(int n) {parent = new int[n];rank = new int[n];// 初始时每个节点的父节点都是它自己for (int i = 0; i < n; i++) {parent[i] = i;}sum = n;}public int find(int x) {while (x != parent[x]) {x = parent[x];}return x;}public void union(int x, int y) {int rootX = find(x);int rootY = find(y);// 如果两个元素的根节点一致,不需要合并if (rootX == rootY) {return;}// 如果根节点 rootX 的深度 > rootY。if (rank[rootX] > rank[rootY]) {// 那么将以rootY作为根节点的集合加入到rootX对应的集合当中rank[rootX] += rank[rootY];// 同时改变rootY的根节点,指向rootX。parent[rootY] = rootX;} else {// 反之rank[rootY] += rank[rootX];parent[rootX] = rootY;}}/*** 判断两个节点是否在同一个集合中*/public boolean connected(int x, int y) {return find(x) == find(y);}
}
二. 运用案例 - 省份数量
原题链接
我们在并查集模板的基础上进行改造:
class UnionFind {private int[] rank;// 每个省份具有的城市数量private int[] parent;// 每个城市对应的根节点(省份)private int sum;// 省份的数量public UnionFind(int[][] isConnected) {int len = isConnected.length;// 初始化,省份数量和提供的城市数量一致sum = len;// 每个集合具有的城市数量为1rank = new int[len];parent = new int[len];Arrays.fill(rank, 1);// 根节点指向自己for (int i = 0; i < len; i++) {parent[i] = i;}}public int find(int x) {while (x != parent[x]) {x = parent[x];}return x;}public void union(int x, int y) {int rootX = find(x);int rootY = find(y);// 如果两个元素的根节点一致,不需要合并if (rootX == rootY) {return;}// 如果根节点 rootX 的深度 > rootY。if (rank[rootX] > rank[rootY]) {// 那么将以rootY作为根节点的集合加入到rootX对应的集合当中rank[rootX] += rank[rootY];// 同时改变rootY的根节点,指向rootX。parent[rootY] = rootX;} else {// 反之rank[rootY] += rank[rootX];parent[rootX] = rootY;}// 合并成功,那么总集合数量要减1sum--;}
}
不过本题目当中,对于rank
这个属性没有什么作用,最终看的是sum属性
。因此大家可以把这个属性相关的给去除。
最后来看代码部分:
public int findCircleNum(int[][] isConnected) {// 初始化构造UnionFind unionFind = new UnionFind(isConnected);int len1 = isConnected.length;int len2 = isConnected[0].length;for (int i = 0; i < len1; i++) {for (int j = 0; j < len2; j++) {// 如果是相连的,那么将城市 i 和 j 合并if (isConnected[i][j] == 1) {unionFind.union(i, j);}}}// 最后返回集合个数(即省份的个数)return unionFind.sum;
}
最终代码如下:
public class Test547 {public int findCircleNum(int[][] isConnected) {UnionFind unionFind = new UnionFind(isConnected);int len1 = isConnected.length;int len2 = isConnected[0].length;for (int i = 0; i < len1; i++) {for (int j = 0; j < len2; j++) {// 如果是相连的,那么将城市 i 和 j 合并if (isConnected[i][j] == 1) {unionFind.union(i, j);}}}return unionFind.sum;}class UnionFind {private int[] rank;// 每个省份具有的城市数量private int[] parent;// 每个城市对应的根节点(省份)private int sum;// 省份的数量public UnionFind(int[][] isConnected) {int len = isConnected.length;// 初始化,省份数量和提供的城市数量一致sum = len;// 每个集合具有的城市数量为1rank = new int[len];parent = new int[len];Arrays.fill(rank, 1);// 根节点指向自己for (int i = 0; i < len; i++) {parent[i] = i;}}public int find(int x) {while (x != parent[x]) {x = parent[x];}return x;}public void union(int x, int y) {int rootX = find(x);int rootY = find(y);// 如果两个元素的根节点一致,不需要合并if (rootX == rootY) {return;}// 如果根节点 rootX 的深度 > rootY。if (rank[rootX] > rank[rootY]) {// 那么将以rootY作为根节点的集合加入到rootX对应的集合当中rank[rootX] += rank[rootY];// 同时改变rootY的根节点,指向rootX。parent[rootY] = rootX;} else {// 反之rank[rootY] += rank[rootX];parent[rootX] = rootY;}sum--;}}
}
相关文章:

想要精通算法和SQL的成长之路 - 并查集的运用和案例(省份数量)
想要精通算法和SQL的成长之路 - 并查集的运用 前言一. 并查集的使用和模板1.1 初始化1.2 find 查找函数1.3 union 合并集合1.4 connected 判断相连性1.5 完整代码 二. 运用案例 - 省份数量 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 并查集的使用和模板 先说一下并查集…...

解决内网拉取企微会话存档代理问题的一种办法
问题:客户的服务都是内网的,不能直接访问外网;访问外网的话需要走kong网关才能出去。 会话存档官网说可以使用socket5、http方式拉取会话存档;我这边尝试了直接使用kong网关的ip和端口配置进去,是访问不了的 我后面就…...

二十二,加上各种贴图
使用pbr的各种贴图,albedo,金属度,ao,法线,粗糙度,可以更好的控制各个片元 1,先加上纹理坐标 texCoords->push_back(osg::Vec2(xSegment, ySegment)); geom->setVertexAttribArray(3, texCoords, osg::Array::BI…...

新版校园跑腿独立版小程序源码 多校版本,多模块,适合跑腿,外卖,表白,二手,快递等校园服务
最新校园跑腿小程序源码 多校版本,多模块,适合跑腿,外卖,表白,二手,快递等校园服务 此版本为独立版本,不需要** 直接放入就可以 需要自己准备好后台的服务器,已认证的小程序…...

SpringBoot banner 样式 自动生成
目录 SpringBoot banner 样式 自动生成 图案网站: 1.第一步创建banner.txt文件 2.访问网站Ascii艺术字实现个性化Spring Boot启动banner图案,轻松修改更换banner.txt文件内容,收集了丰富的banner艺术字和图,并且支持中文banner下…...

回收站里面删除的照片如何恢复?
现在拍照已经成为人们生活中的一种方式,照片为我们保留了许多珍贵而美好的回忆。大家通常会把重要的照片保存在硬盘里,但当不小心把照片移入回收站并彻底删除时,情况就有点糟糕了。那么,回收站里删除的照片还有办法恢复吗…...
Qt model/view 理解 2
这是我对 Qt 的 model/view 内容理解的第二篇 blog,在第一篇文章中,介绍 QTableView 和 QAbstractTableModel,实现显示了对数据源的显示,但是显示的格式和修改的模式都是按照 View 控件的自显示方式。在此,使用 Qt 自带…...

【LeetCode热题100】--114.二叉树展开为链表
114.二叉树展开为链表 方法一:对二叉树进行先序遍历,得到各个节点被访问到的顺序,利用数组存储下来,然后在先序遍历之后更新每个节点的左右节点的信息,将二叉树展开为链表 /*** Definition for a binary tree node.* …...

Java | Maven(知识点查询)
文章目录 Maven知识速查1. Maven概述2. Maven的作用3. Maven的下载4. Maven的环境配置5. Maven 的基础组成5.1 Maven仓库5.1.1 本地仓库配置:5.1.2 中央仓库配置:5.1.3 镜像仓库配置 5.2 Maven坐标 6. Maven项目6.1 手工创建Maven项目6.2 自动构建项目 7…...

Vmware 静态网络配置
概述 仅主机模式(VMware1):使用host-only的方式是不能和外界通信的,只能够和本机的物理网卡通信 桥接(VMnet0):使用桥接的方式使得自己的虚拟机和自己的真实机网卡在同一个网段 NAT࿰…...

【数据结构--八大排序】之希尔排序
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …...
Linux中生成so库的文件引用另一个so库问题的解决
文章目录 一、问题介绍二、问题解决 一、问题介绍 由于项目需求,需要将一个“编译时引用了另一个动态链接库”的文件(名为main.c),再编译成一个动态链接库。 简要说明一下,即原本的项目代码里,包含main.c…...
EDI是连接原始电子商务和现代电子商务的纽带
EDI是连接原始电子商务和现代电子商务的纽带。 EDI(Electronic Data Interchange,电子数据交换)是一种电子通信技术,用于在不同组织之间以结构化和标准化的方式交换业务文档和数据。EDI使企业能够更有效地与供应商、客户和合作伙…...

星宿UI2.4资源付费变现小程序源码 支持流量主
第一个小程序为星宿小程序 目前是最新版2.0 搭建星宿需要:备用域名 服务器 微信小程序账号 功能:文章展示 文章分类 资源链接下载 轮播图 直接下载附件功能 很多 很适合做资源类分享 源码下载:https://download.csdn.net/download/m0_6604…...
代码随想录训练营二刷第四十六天 | 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ
代码随想录训练营二刷第四十六天 | 518. 零钱兑换 II 377. 组合总和 Ⅳ 一、518. 零钱兑换 II 题目链接:https://leetcode.cn/problems/coin-change-ii/ 思路:完全背包求组合数,递推公式dp[j]dp[j-nums[i]]。 求组合数,物品在外…...

python安装第三方模块方法
正常情况下安装python第三方模块没啥说的,但是由于python安装模块默认是在外网下载安装,牵扯外网网速问题,所以可以配置下使用国内某镜像源来下载模块 python -m pip install xxxxxxxxxxx 和 pip install xxxxxxxxxx 的命令都可下载安装第三…...
广西小贷公司设立及小贷牌照申请政策要求
关于广西小额贷款公司设立及小贷牌照申请,依据《关于小额贷款公司试点的指导意见》(银监发〔2008〕23号);《广西壮族自治区小额贷款公司管理办法》(桂政发〔2009〕71号);《广西壮族自治区人民政…...
PyTorch应用实战二:实现卷积神经网络进行图像分类
文章目录 实验环境MNIST数据集1.网络结构2.程序实现2.1 导入相关库2.2 构建卷积神经网络模型2.3 加载MNIST数据集2.4 训练模型 附:系列文章 实验环境 python3.6 pytorch1.8.0 import torch print(torch.__version__)1.8.0MNIST数据集 MNIST数字数据集是一组手写…...
面试系列 - Java常见算法(二)
目录 一、排序算法 1、插入排序(Insertion Sort) 2、归并排序(Merge Sort) 二、图形算法 1、最短路径算法(Dijkstra算法、Floyd-Warshall算法) Dijkstra算法 Floyd-Warshall算法 2、最小生成树算法&…...

Cortex-A9 架构
一、Cortex-A 处理器运行模式 Cortex-A9处理器有 9中处理模式,如下表所示: 九种运行模式 在上表中,除了User(USR)用户模式以外,其它8种运行模式都是特权模式,在特权模式下,程序可以访问所有的系统资源。这…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...