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

并查集—数组实现

文章目录

  • 前言
  • 题目
  • 用例
  • 解答
    • 并查集
    • 输入
  • 优化


前言

给一堆不重复的元素分组,判别两个元素是否在同一组中,可以使用并查集数据结构。并查集的实现可以用数组,链表,树。这里我们用最简单的数组。

题目

在这里插入图片描述

用例

在这里插入图片描述
在知道并查集之前,我想到的是用ArrayList数组,元素类型为HashSet,每一组就对应一个HashSet,再来一张HashMap,类似于一张成员组号表,成员是key,组号是value。在Map里查询:
1.没查到,创建新HashSet,添加新组;
2.查到一个,就把另一个加入查到的组;
3.都查到但是组别不一样,就合并组别。

这样一来可以解题,但是所用的数据结构以及代码都过于冗杂。我的解答就不做参考,直接看标准解答。

解答

并查集

我们常常说数据结构与算法,他们的关系可以看作 :好的数据结构可以简化算法。接下来用数组来实现并查集。

并查集可以看作每一组都有严格的等级制度,一个组内有大组长,小组长,组员等等。判断一个人在哪一组只需要从下往上找找到组长即可。

例如有五个人,初始化五个人分别代表五个组,然后2加入1组(认一组组长1做组长),3加入2所在组。
在这里插入图片描述
现在问3在哪一组,就可以通过索引层层往上,直到索引index和value相等。

arr[3]是2,arr[2]是1,arr[1]是1,OK查找完毕,3和1是一组的。这个过程的逻辑其实是一个嵌套。而且在已知3是1组后,就可以把arr[3]的value改为1,下次查找的时候更快,减少时间复杂度,因为嵌套的特性,这一组的value都会被改为1。

属性一个数组即可
方法查找根结点;合并组别;

查找根结点

int[] fa;public UnionFindSet(int n){this.fa = new int[n];for (int i=0;i<n;i++) {this.fa[i] = i;
}public int find(int x){return this.find(this.fa[x]);
}

如果不加限制条件,达到根结点后会一直嵌套,内存泄漏。应当添加判断是否到达根节点:

public int find(int x){if (this.fa[x] != x) {return this.find(this.fa[x]);}return x;
}

其实就是到达根节点this.fa[x] == x直接返回,不再嵌套。

但这还没有压缩路径,我们需要把每次找到的父级value赋给子级value

public int find(int x){if(this.fa[x] != x) {return this.fa[x] = this.find(this.fa[x]);}return x;
}

有了find函数,组合函数和整套代码就变得小菜一碟。

如果x,y的value不等,选x的组长作为合并组的组长。y的组长投靠x的组长即可。

public void union(int x,int y){int x_fa = this.find(x);int y_fa = this.find(y);if(x_fa != y_fa) {this.fa[y_fa] = x_fa;}
}

写好并查集这个数据结构,按照题目要求写逻辑即可。

输入

这道题不可输入输出写在一个循环里,否则可能造成输入一行,输出一行,不满足题目要求。此时我们可以先用二维数组把输入的abc保存下来。

Scanner sc = new Scanner(System.in);
int n = sc.nextInt(),m = sc.nextInt();
int[][] inputs = new int[m][3];
for (int i=0;i<m;i++) {inputs[i][0] = sc.nextInt();inputs[i][1] = sc.nextInt();inputs[i][2] = sc.nextInt();
}

int a = 0,b = 0, c = 0;
UnionFindSet union = new UnionFindSet(n+1);
for (int i=0;i<m;i++) {a = inputs[i][0];b = inputs[i][1];c = inputs[i][2];int teamIndexA = union.find(a);int teamIndexB = union.find(b);if (c != 0 && c!= 1 || a < 1||b<1||a>n||b>n) {System.out.println("da pian zi");}else if (c == 0) {if (teamIndexA != teamIndexB) {union.union(a,b);}} else if (c == 1){if (teamIndexA == teamIndexB) {System.out.println("we are a team");} else {System.out.println("we are not a team");}}

优化

我将判断输入是否合法以及判断如何输出放在了一个if里面,可以分开,增加代码的可读性和可维护性。并且判断不合法后,continue进入下一次循环,防止出现数组下标越界访问等不可控问题。

打印we are a team或者not a team时,由于只有两种选项,可以用三目表达式。

            if (c != 0 && c!= 1 || a < 1||b<1||a>n||b>n) {System.out.println("da pian zi");continue;}if (c == 0) {if (teamIndexA != teamIndexB) {union.union(a,b);}} else if (c == 1){System.out.println(teamIndexA==teamIndexB?"we are a team":"we are not a team");//                if (teamIndexA == teamIndexB) {
//                    System.out.println("we are a team");
//                } else {
//                    System.out.println("we are not a team");
//                }}

http://www.mrgr.cn/news/93275.html

相关文章:

  • 全局异常处理器为什么不能处理过滤器异常,有那些解决方案
  • FLEXOO的传感器技术:从材料选择到生产工艺的全方位创新
  • Windows零门槛部署DeepSeek大模型:Ollama+7B参数模型本地推理全攻略
  • 在Ubuntu上搭建Samba服务,实现与windows之间的文件共享
  • 蓝桥杯真题
  • hi3516cv610适配AIC8800D80的连接路由器记录
  • leetcode1 两数之和 哈希表
  • Spring(三)容器-注入
  • FreeRTOS列表和列表项
  • 审批流AntV框架蚂蚁数据可视化X6饼图(注释详尽)
  • win11不能访问到共享文件
  • 多线程-线程池
  • AI 实战5 - pytorch框架实现face检测
  • 在S32K3上实现SOC的神经网络算法的可行性
  • io函数 day3 文件io与系统函数
  • 一篇文章讲解清楚ARM9芯片启动流程
  • ​Unity插件-Mirror使用方法(八)组件介绍(​Network Behaviour)
  • K8s 1.27.1 实战系列(一)准备工作
  • FastExcel/EasyExcel简介以及源码解析
  • 尚庭公寓项目记录