并查集的实现与应用(力扣)

并查集的实现与应用(力扣)

  • 并查集的实现
  • 力扣323 130 990


学习地址

并查集的实现

package com.caoii;/**@program:labu-pratice-study*@package:com.caoii*@author: Alan*@Time: 2024/4/12  21:53*@description: 并查集的实现*/public class UnionFind {// 记录连通分量private int count;// 节点X的父节点 是 parent[x]private int[] parent;//使用一个size数组  记录每棵树包含的节点数目//来让两个树合并的时候尽量让小的树接到大的树的下面//这样每次使用find向上找根节点的复杂度能相对减少//private int[] size;// 通过改造find函数 可将每个树都变成 真正高度为2// 即 每个子节点都直接与最高根节点相连的样式// 故size就不必再使用了// 构造函数 n 为 图的节点数目public UnionFind(int n) {this.count = n;// 一开始互不连通 则 连通分量的数目等于节点数目parent = new int[n];// 父节点指针初始时指向自己for (int i = 0; i < n; i++) {parent[i] = i;//size[i] = 1;}// 若两个节点被连通 则其中任意一个节点的根节点指针指向另一个节点}/*将p和q 所在的连通分量进行 链接*/public void union(int p, int q) {int rootP = find(p);int rootQ = find(q);// find方法获取两个树的最高根节点if (rootP == rootQ) {// 两棵树已经连通则最高根节点一定相同// 不需要 再次链接 直接退出方法return;}/*改进find之后不用size了//两棵树最高根节点不同的时候://两棵树合并为一棵树  设置P的根节点为Qif (size[rootP] > size[rootQ]) {parent[rootQ] = rootP;size[rootP] += size[rootQ];// P树更高 则 把 Q树接在P树下面,让Q的父节点指针指向P// P的高度增加// 实际上此时所说的高度不是真的高度而是该树的全部节点个数} else {parent[rootP] = rootQ;size[rootQ] += size[rootP];}*///两棵树最高根节点不同的时候://两棵树合并为一棵树  设置P的根节点为Qparent[rootP] = rootQ;count--;// 两个分量合二为一   分量数目减一}/*返回某个节点X的最高根节点*/public int find(int x) {/*传统方法  逐次向上寻找最高根节点while (parent[x] != x) {x = parent[x];}return x;// 若根节点指针指向自己,则返回自己// 若根节点指针没有指向自己,则把根节点指针指向的元素赋值给X 并循环判断// 若 3-->5-->6  则 X=3时执行:x=5 ——> 5!=parent[5]=6 ——> x=6 ——> 6=parent[6]=6 ——> return 6*/// 改进方法 在寻找最高根节点的过程中// 将树构造为 真实高度为2 所有子节点都与根节点直接相连的形式:if (parent[x] != x) {// x的根节点 不是 x 自己// 则x 存在根节点parent[x] = find(parent[x]);// 递归运算// 最后:}return parent[x];// 递归出口: 递归到最高层根节点 此时 x==parent[x] 所以返回x// 则 次高层处节点为y,  parent[y] = find(parent[y]) = x// 即次高层处节点的父指针指向最高节点// 同理 次次高层处节点为z,  parent[z] = find(parent[z]) = find(y) = parent[y] = x// 即次次高层处节点的父指针指向最高节点x// 以此类推// 最后结果就是所有子节点都直接与根节点直接相连  树的真是高度为2}/*判断 p 和 q 是否连通*/public boolean connected(int p, int q) {int rootP = find(p);int rootQ = find(q);return rootP == rootQ;// 若两个树的最高节点相同则p与q连通}/*返回图中有多少个连通分量*/public int count() {return count;}
}

力扣323 130 990

package com.caoii;/**@program:labu-pratice-study*@package:com.caoii*@author: Alan*@Time: 2024/4/12  23:25*@description: 并查集相关题目测试*/import org.junit.jupiter.api.Test;public class UFTest {/** 力扣323题* 给你输入一个包含 n 个节点的图,用一个整数 n 和一个数组 edges 表示,* 其中 edges[i][j] = [ai, bi] 表示图中节点 ai 和 bi 之间有一条边。* 请你计算这幅图的连通分量个数。*/public int countComponents(int n, int[][] enges) {int count = n;// 初始时 连通分量个数等于节点个数UnionFind unionFind = new UnionFind(n);for (int[] e : enges) {unionFind.union(e[0], e[1]);// 链接 ai 与 bi}count = unionFind.count();// 返回 完成全部链接后 最少的连通分量个数return count;}/*测试323题*/@Testpublic void test_01() {int n = 11;// un中的parent[] 为 0-10int[][] enges = {{0, 6}, {6, 0},{1, 2}, {1, 3}, {2, 1}, {2, 3}, {2, 4},{3, 1}, {3, 2}, {3, 5}, {4, 2},{6, 7}, {7, 6},{8, 9}, {9, 8}, {9, 10}, {10, 9}};System.out.print("该无向图的连通分量个数为: " + countComponents(n, enges));}/*力扣130给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。*/public void solve(char[][] board) {// 用并查集解决// 将二维数组映射为一维数组if (board.length == 0) {return;}int m = board.length;//行数int n = board[0].length;//列数// board[a][b] ==> temp[x*n+y]  x从0-(board.length-1)// temp的index从0-(lengthAll-1)UnionFind unionFind = new UnionFind(m * n + 1);// 用一个一维数组设置并查集对象// 多设置一个空位存储一个虚构的根节点int dummy = m * n; // 此根节点的索引值为m*n// 将首列与末列的O与dummy相连for (int i = 0; i < m; i++) {if (board[i][0] == 'O') {unionFind.union((i * n + 0), dummy);}if (board[i][n - 1] == 'O') {unionFind.union((i * n + n - 1), dummy);}}// 将首行与末行的O与dummy 相连for (int j = 0; j < n; j++) {if (board[0][j] == 'O') {unionFind.union((0 * n + j), dummy);}if (board[m - 1][j] == 'O') {unionFind.union((m - 1) * n + j, dummy);}}// 设置方向数组dint[][] d = new int[][]{{0, 1},{1, 0},{0, -1},{-1, 0}};// 三层循环结束后 与dummy链接到同一个分量的O应该都不被转变为Xfor (int i = 1; i < m - 1; i++) {for (int j = 1; j < n - 1; j++) {if (board[i][j] == 'O') {for (int k = 0; k < 4; k++) {int x = i + d[k][0];int y = j + d[k][1];// i 与 j 分别 加(0,1)(1,0)(0,-1)(-1,0)// 向四个方向探索是否存在Oif (board[x][y] == 'O') {unionFind.union((x * n + y), i * n + j);// 四个方向任意一个有相邻的就合并分量}}}}}// 将非dummy集合的O都设置为Xfor (int i = 1; i < m - 1; i++) {for (int j = 1; j < n - 1; j++) {if (board[i][j] == 'O') {if (!unionFind.connected(dummy, i * n + j)) {board[i][j] = 'X';}}}}for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {System.out.print(board[i][j] + " ");}System.out.println();}}@Testpublic void test_02() {char[][] board = new char[][]{{'X', 'X', 'X', 'X'},{'X', 'O', 'O', 'X'},{'X', 'X', 'O', 'X'},{'X', 'O', 'X', 'X'}};solve(board);}/*力扣 990 题给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false示例 1:输入:["a==b","b!=a"]输出:false解释:如果我们指定,a = 1 且 b = 1,那么可以满足第一个方程,但无法满足第二个方程。没有办法分配变量同时满足这两个方程。示例 2:输入:["b==a","a==b"]输出:true解释:我们可以指定 a = 1 且 b = 1 以满足满足这两个方程。示例 3:输入:["a==b","b==c","a==c"]输出:true示例 4:输入:["a==b","b!=c","c==a"]输出:false示例 5:输入:["c==c","b==d","x!=z"]输出:true*/public boolean equationsPossible(String[] equations) {UnionFind unionFind = new UnionFind(26);for (int i = 0; i < equations.length; i++) {if (equations[i].charAt(1) == equations[i].charAt(2)) {// == 情况unionFind.union((int) (equations[i].charAt(0) - 'a'), (int) (equations[i].charAt(3) - 'a'));}}for (int i = 0; i < equations.length; i++) {if (equations[i].charAt(1) != equations[i].charAt(2)) {// != 情况if (unionFind.connected((int) (equations[i].charAt(0) - 'a'), (int) (equations[i].charAt(3) - 'a'))) {// 如果 在不等于的条件下 发现 他俩已经放入同一个集合了return false;}}}return true;}@Testpublic void test_03() {String[] equations = {"a==b", "b!=c", "a==c"};System.out.println(equationsPossible(equations));}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/812675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web中使用Weblogic用户

WebLogic用户&#xff0c;组设置 1. 登录weblogic console, domain结构中选择Security Realms&#xff0c;显示安装时默认创建的Realm &#xff1a; myrealm 2. 点击myrealm, 选择 users and Group&#xff0c; 追加用户和组 选择既存的权限组追加到新规的组中&#xff0c;赋予…

servicecomb bmi例子无法正常启动

前端报错404&#xff0c;后端显示&#xff1a;[ntloop-thread-7] o.a.s.c.rest.locator.OperationLocator : locate path failed, status:Not Found, http method:GET, path:/, microserviceName:gateway 原因&#xff1a; 在resource-->application.yml中&#xff1a; # …

java智慧校园系统源码saas电子班牌固件安卓7.1+Java Android原生系统源码

java智慧校园系统源码saas电子班牌固件安卓7.1&#xff0b;Java Android原生系统源码 智慧校园是促进信息技术与教育教学深度有效融合、提高学与教的效果为目的&#xff0c;以物联网、云计算、大数据分析等新技术为核心技术&#xff0c;提供一种环境全面感知、智慧型、数据化、…

数据结构——简单二叉树的性质和遍历

二叉树 两个值得注意的性质&#xff1a; 1.二叉树是有序树&#xff0c;这个我想了很久不知道为什么&#xff0c;可是为什么二叉树只有三种遍历方式&#xff0c;而不是六种&#xff1f;说明每个形态不同的树都有不同的含义。那完全二叉树和平衡二叉树呢&#xff1f;也是一样的…

.NET/C#汇总 —— 多线程

1.根据线程安全的相关知识,分析以下代码,当调⽤test⽅法时i>10时是否会引起死锁?并简要说 明理由。 public void test(int i) {lock(this){if (i>10){i--;test(i);}} } 不会发⽣死锁,(但有⼀点int是按值传递的,所以每次改变的都只是⼀个副本,因此不会出现死锁。…

Linux 删除文件或文件夹命令(新手)

一、删除文件夹 rm -rf 路径/目录名 1 强制删除文件夹及其子文件。 二、删除文件/文件夹&#xff1a;rm 命令 rm 删除命令&#xff0c;它可以永久删除文件系统中指定的文件或目录。 rm [选项] 文件或目录 选项&#xff1a; -f&#xff1a;强制删除&#xff08;force&am…

前端大屏项目适配方法

要在F11全屏模式下查看 方法一&#xff0c;rem font-size 动态设置HTML根字体大小 和 body 字体大小&#xff08;lib_flexible.js&#xff09; 将设计稿的宽&#xff08;1920&#xff09;平均分成 24 等份&#xff0c; 每一份为 80px。HTML字体大小就设置为 80 px&#xff…

SonarQube 9.9.4 LTS社区版安装

目标 安装个SonarQube社区版. 安装SonarQube9.9.4 LTS社区版 https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-9.9.4.87374.zip # 切换到安装目录 cd /opt # 下载安装包 sudo wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube…

[管理者与领导者-160] :社交策略和智慧-3,如何用积极的语言表达他人的赞美,构建和谐的人际关系

目录 一、用积极的语言表达他人的赞美他人的重要性 1.1 消极语言的危害 1.2 批评性语言的危害 1.3 积极的语言表达他人的赞美他人的重要性 二、有哪些积极的赞美他人的语言&#xff1f; 2.1 有哪些消极性语言 2.2 有哪些积极性语言 2.3 有哪些批评性语言 2.4 有哪些赞…

C语言--结构体大小

基本数据类型占用的字节数分别为:char(1),short(2),int(4),long(4),long long(8),float(4),double(8)。 分析一下下面结构体占用的字节数。 struct A { int a; }; struct B { char a; int b; }; int main() { printf("sizeof(struct A)%d\n", sizeof(struct A));//测…

Nginx小册(博客笔记迁移)

nginx基础 1.常用命令 nginx -v #查看版本 ps -ef | grep nginx #输出linux进程、 nginx #启动nginx进程 nginx -s reload #重载配置 nginx -s stop # 停止进程 nginx -t # 检查是否有语法错误&#xff0c;以及配置文件地址2.nginx的配置文件 # 用户组的设置 windows上不生…

Java面试题:什么是Java的集合框架?详细举例说明常用的集合,及其应用场景

Java的集合框架&#xff08;Java Collections Framework&#xff09;是Java编程语言中提供的一套用于表示和操作集合的统一架构。它包含了一系列接口、类和算法&#xff0c;用于创建和操作集合对象&#xff0c;如列表、集合、映射等。这些集合对象在Java程序中广泛用于存储和组…

支持0V充电700MA线性锂电池充电芯片-YB4055SL

支持0V充电700MA线性锂电池充电芯片 描述&#xff1a; YB4055SL是一款完整的单节锂离子电池采用恒定电流/恒定电压线性充电器。其SOT 封装与较少的外部元件数目使得YB4055SL成为便携式应用的理想选择YB4055SL可以适合 USB 电源和适配器电源工作。 由于采用了内部PMOSFET架构&am…

微信小程序 uniapp+vue.js医疗在线问诊挂号系统4oy17

预约挂号系统的逐渐发展&#xff0c;进一步方便了广大用户&#xff0c;使其可以更方便、快捷地预约挂号&#xff0c;并且也有效地防止号贩子“倒号”&#xff0c;使用户预约挂号更公平&#xff0c;然而现有预约挂号系统或多或少有所欠缺 小程序前端框架&#xff1a;uniapp 小程…

AndroidAutomotive模块介绍(三)CarService服务

前言 上一篇文档总结 Android Automotive 框架的 APP 和 API 部分内容&#xff0c;本篇文档将会继续根据 Android Automotive 框架结构&#xff0c;总结 Framework 层 CarService 服务的内容。 本文档对 Android Automotive Framework 层服务将会按照如下顺序展开描述&#x…

windows搭建ftp服务器

安装iis 点击安装即可,搜索iis打开 创建ftp服务器 身份验证&#xff1a;只勾选匿名&#xff0c;不勾选基本&#xff0c;网上的很多教程会添加基本&#xff0c;导致的问题会出现浏览提需要输入账号密码的情况&#xff0c;这里为了方便大家更直观的感受FTP建立的过程&#xff0…

计算机网络技术-双绞线的制作与测试方法

目录 制作方法测试方法 待续、更新中 制作方法 &#xff08;1&#xff09;剥线 (2&#xff09;去除外表皮 &#xff08;3&#xff09;分开双绞线 (4&#xff09;拆分线对 &#xff08;5&#xff09;排列线序 &#xff08;6&#xff09;剪线 &#xff08;7&#xff09;安装RJ-4…

物理服务器与云服务器的租用对比

​ 物理服务器&#xff1a;每个基于 Web 的应用程序都依赖于一个服务器&#xff0c;该服务器提供网络中的数据存储&#xff0c;并可根据请求提供给客户端。例如&#xff0c;用户使用浏览器访问 Web 应用程序。服务器可确保托管客户端可以使用该硬件组件。与其他托管可能性相比&…

MySQL数据库max_allowed_packet参数

如上图所示的报错&#xff0c;我在提交接口的时候出现了这个错误&#xff1a; MySqlConnector.MySqlException:Error submitting 4MB packet;ensure max_allowed_packet is greater than 4MB.在MySQL数据库中&#xff0c;有一个参数叫max_allowed_packet&#xff0c;这个参数会…

nacos服务器挂了之后springboot/springcloud服务会挂吗?不会挂(顺便深入源码分析nacos配置中心客户端核心功能实现)

文章目录 nacos挂了之后服务会挂吗&#xff1f;不会挂&#xff08;深入源码分析&#xff09;展开nacos客户端源码找本地缓存配置相关文件客户端内存缓存客户端健康状态获取配置的实现 nacos挂了之后服务会挂吗&#xff1f;不会挂&#xff08;深入源码分析&#xff09; 展开nac…