并查集与LRUCache

一)并查集

在一些应用问题中,需要将N个不同的元素划分成一些互不相交的集合,开始的时候,每一个元素自成一个单元素集合,然后按照一定的规律将归于同一组元素的集合进行合并,并且在此过程中需要反复使用到查询某一个元素是属于哪一个集合,适合于描述这种抽象问题的数据类型称之为是并查集

1)假设某公司今年校招全国一共招生10人,西安招4人,成都招三人,武汉招四人,10个人来自于不同的学校,起初这10个人之间相互都不认识,每一个学生都是一个独立的小团体,现在给这些学生进行编号,{0,1,2,3,4,5,6,7,8,9},给以下数组用于存储小集体

2)毕业以后发现,学生们要去公司上班,每一个地方的学生自发的组织小分队开始上路,于是西安学生小分队{0,6,7,8},武汉学生小分队{2,3,5},成都学生小分队{1,4,9},每一个小分队的人的第一位同学当队长,带领大家找工作,这样的原来每一个地区互相不认识的几个人现在都相互认识了

4)从上图可以看出:编号6,7,8同学属于0号小分队,该小分队中有4人(包含队长0),编号为4和9的同学属于1号小分队,该小分队有3人(包含队长1),编号为3和5的同学属于2号小分队,该小分队有3个人(包含队长1)

5)从这里可以总结:

5.1)数组的下标代表集合中元素的编号

5.2)数组中下标的数如果代表的是负数,那么数组的下标的编号就是队长,此时这个负号代表这个下标就是此树形关系中的根节点,数字代表以当前下标为根节点的这棵二叉树中有多少元素

5.3)数组中如果某一个下标的数代表是非负数那么这个非负数代表的是这个下标的父亲节点

6)假设此时在公司工作一段时间后,西安小分队中8号同学与成都小分队1号同学奇迹般的走到了一起,两个小圈子的学生相互介绍,最后成为了一个小圈子

7)现在0集合中有7个人,2集合中有3个人,一共有两个朋友圈,通过上述例子可知,并查集可以解决下面的几个问题:

7.1)查找元素属于哪一个集合:沿着数组表示的属性关系以上找到根,根节点就是数组下标中元素是负数的位置

7.2)查看两个元素是否属于同一个集合:沿着数组表示的属性关系向上一直找到树的根,如果跟相同则表明是在同一个集合中,否则不在同一个集合中

7.3)将两个集合合并成1个集合:可以将两个集合中的元素进行合并,将一个集合中的名称改成另一个集合的名称

7.4)集合的个数:遍历整个数组,数组中元素是负数的个数就是集合中元素的个数

合并两个集合:

1)当合并两个数的时候, 这两个数必须来自于不同的集合,就拿上面的6和7来进行举例,这两个数本身都在同一个集合中了,因此对于他们的合并是没有任何意义的,所以如果给定两个数,如果他们的根节点相同,那么就不需要进行合并,所以合并一定是两个不同的集合中的元素;

2)以上面的这种图进行举例,假设要合并4和8所在的元素集合,首先找到根节点,分别是index1和index2

2.1)array[index1]=array[index1]+array[index2],这里面是更新新的根节点中的元素个数,更新孩子的数量

2.2)array[index2]=index1,更新另一棵树的根节点

public class UnionFindSet {public int[] array;public int usedSize;public UnionFindSet(int n){//n代表数组长度this.array=new int[n];Arrays.fill(array,-1);}public boolean isUnionSet(int x,int y){//查询x和y是否在同一个集合,就需要判断x和y的根节点是否相同int father1=findRoot(x);int father2=findRoot(y);return father1==father2;}public int findRoot(int data){//查找数据x的根节点if(data<0) throw new ArrayIndexOutOfBoundsException("此时data不能不是负数");while(array[data]>=0){data=array[data];}return data;//此时返回的是根节点,而不是根节点对应的数字,此时下标已经代表的是根节点的数值了}//合并两个集合public void union(int x,int y){int father1=findRoot(x);int father2=findRoot(y);if(father1==father2){System.out.println("两个元素是属于同一个集合中的不需要进行合并");return;}array[father1]=array[father1]+array[father2];//选取father1来充当合并以后的根节点3array[father2]=father1;//更新被合并的那个数的根节点}//查找集合的个数public int GetCount(){int count=0;for(int num:array){if(num<0) count++;}return count;}public static void main(String[] args) {//根据上面这个合并的代码要重点理解合并的过程:UnionFindSet set=new UnionFindSet(100);//1.先合并0,6,7,8set.union(0,6);set.union(7,8);set.union(0,7);//2.在合并1 4 9set.union(1,4);set.union(4,9);//3.最后合并2 3 5set.union(2,3);set.union(3,5);//4.观察最终结果System.out.println(Arrays.toString(set.array));set.union(8,1);
//set.union(1,8)得到的就是index2也就是8充当根节点System.out.println(Arrays.toString(set.array));System.out.println(set.isUnionSet(6,9));//也可以判断他们是否是同一个亲戚}
}

并查集——亲戚(洛谷 P1551)_并查集试炼之亲戚_是一只派大鑫的博客-CSDN博客

并查集的应用:
1)省份数量:

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

class UnionFindSet {public int[] array;public int usedSize;public UnionFindSet(int n){//n代表数组长度this.array=new int[n];Arrays.fill(array,-1);}public boolean isUnionSet(int x,int y){//查询x和y是否在同一个集合,就需要判断x和y的根节点是否相同int father1=findRoot(x);int father2=findRoot(y);return father1==father2;}public int findRoot(int data){//查找数据x的根节点if(data<0) throw new ArrayIndexOutOfBoundsException("此时data不能不是负数");while(array[data]>=0){data=array[data];}return data;//此时返回的是根节点,而不是根节点对应的数字,此时下标已经代表的是根节点的数值了}//合并两个集合public void union(int x,int y){int father1=findRoot(x);int father2=findRoot(y);if(father1==father2){System.out.println("两个元素是属于同一个集合中的不需要进行合并");return;}array[father1]=array[father1]+array[father2];//选取father1来充当合并以后的根节点3array[father2]=father1;//更新被合并的那个数的根节点}//查找集合的个数public int GetCount(){int count=0;for(int num:array){if(num<0) count++;}return count;}
}
class Solution {public int findCircleNum(int[][] array) {UnionFindSet set=new UnionFindSet(array.length);for(int i=0;i<array.length;i++){for(int j=0;j<array[0].length;j++){if(array[i][j]==1){set.union(i,j);}}}return set.GetCount();}
}
2)等式方程的可满足性

990. 等式方程的可满足性 - 力扣(LeetCode)

1)根据题目解析可以看到,如果发现字符串的第二个位置是等于号,那么代表这两个位置的字符是相等的,就可以合并,如果是!那么代表这两个字符不是相等的,就不能合并

2)算法原理:

2.1)如果发现str.charAt(1)=='='那么说明这个字符串主要做的就是一个合并操作,那么只需要把str.charAt(0)和str.charAt(3)对应的字符进行合并即可

2.2)如果在发现遍历整个字符串的过程中,str.charAt(1)=="!",说明此时这个字符串的功能执行的不是一个将两个字符串的合并操作,而是一个检查操作,此时就需要检查str.charAt(0)和str.charAt(3)是否合并过,如果是合并过的,直接返回false,否则直接返回true;

 class UnionFindSet {public int[] array;public int usedSize;public UnionFindSet(int n){//n代表数组长度this.array=new int[n];Arrays.fill(array,-1);}public boolean isUnionSet(int x,int y){//查询x和y是否在同一个集合,就需要判断x和y的根节点是否相同int father1=findRoot(x);int father2=findRoot(y);return father1==father2;}public int findRoot(int data){//查找数据x的根节点if(data<0) throw new ArrayIndexOutOfBoundsException("此时data不能不是负数");while(array[data]>=0){data=array[data];}return data;//此时返回的是根节点,而不是根节点对应的数字,此时下标已经代表的是根节点的数值了}//合并两个集合public void union(int x,int y){int father1=findRoot(x);int father2=findRoot(y);if(father1==father2){System.out.println("两个元素是属于同一个集合中的不需要进行合并");return;}array[father1]=array[father1]+array[father2];//选取father1来充当合并以后的根节点3array[father2]=father1;//更新被合并的那个数的根节点}//查找集合的个数public int GetCount(){int count=0;for(int num:array){if(num<0) count++;}return count;}
}
class Solution {public boolean equationsPossible(String[] strings) {UnionFindSet set=new UnionFindSet(26);for(String str:strings){if(str.charAt(1)=='='){set.union(str.charAt(0)-'a',str.charAt(3)-'a');//防止数组越界}}for(String str:strings){if(str.charAt(1)=='!'){int father1=set.findRoot(str.charAt(0)-'a');int father2=set.findRoot(str.charAt(3)-'a');if(father1==father2) return false;}}return true;}
}

二)LRUCache

linkedHashMap双向链表+哈希表,会根据你插入的顺序来输出最终的结果

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

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

相关文章

使用grubby更改RHEL7/8/9的默认内核

使用grubby更改RHEL7/8/9的默认内核 验证默认内核版本获取当前默认内核的索引号检查所有内核的详细信息检查已安装的内核 更改默认内核引导条目使用索引号更改默认内核引导条目 验证默认内核版本 参考&#xff1a;https://linux.cn/article-16147-1.html # 验证默认内核版本 …

炫云云渲染3ds max效果图渲染教程

很多人在第一次使用炫云云渲染渲染效果图的时候不知道怎么使用&#xff0c;其实现在使用炫云渲染效果图真的很简单&#xff0c;我们一起来看看。 一客户端安装 1、打开炫云云渲染官网&#xff0c;点击右上角的客户端下载&#xff0c;选择炫云客户端&#xff08;NEXT版&#xf…

【JavaEE】多线程(三)

多线程&#xff08;三&#xff09; 续上文&#xff0c;多线程&#xff08;二&#xff09;&#xff0c;我们已经讲了 创建线程Thread的一些重要的属性和方法 那么接下来&#xff0c;我们继续来体会了解多线程吧~ 文章目录 多线程&#xff08;三&#xff09;线程启动 startsta…

华为云云耀云服务器L实例评测|cento7.9在线使用cloudShell下载rpm解压包安装mysql并开启远程访问

文章目录 ⭐前言⭐使用华为cloudShell连接远程服务器&#x1f496; 进入华为云耀服务器控制台&#x1f496; 选择cloudShell ⭐安装mysql压缩包&#x1f496; wget下载&#x1f496; tar解压&#x1f496; 安装步骤&#x1f496; 初始化数据库&#x1f496; 修改密码&#x1f4…

实验4 交换机端口隔离(access模式)

交换机端口隔离&#xff08;access模式&#xff09; 实验目的实验拓扑实验步骤&#xff08;1&#xff09;在未划分vlan前&#xff0c;配置pc1、pc2的地址&#xff0c;如图所示&#xff08;2&#xff09;测试两台pc机的连通性&#xff08;3&#xff09;创建vlan&#xff0c;并验…

Day66|图part5:130. 被围绕的区域、827.最大人工岛

130. 被围绕的区域 leetcode链接&#xff1a;题目链接 这题看起来很复杂&#xff0c;其实跟之前找飞地和找边缘地区的是差不多的&#xff0c;主要分三步&#xff1a; 使用dfs将边缘的岛都找出来&#xff0c;然后用A代替防止混淆&#xff1b;再用dfs找中间不与任何岛相连的飞地…

【码银送书第七期】七本考研书籍

八九月的朋友圈刮起了一股晒通知书潮&#xff0c;频频有大佬晒出“研究生入学通知书”&#xff0c;看着让人既羡慕又焦虑。果然应了那句老话——比你优秀的人&#xff0c;还比你努力。 心里痒痒&#xff0c;想考研的技术人儿~别再犹豫了。小编咨询了一大波上岸的大佬&#xff…

UDP与TCP报头介绍,三次握手与四次挥手详谈

先介绍我们UDP/TCP协议缓冲区 在UDP和TCP在数据传输和介绍时有有缓冲区概念的。 UDP缓冲区 UDP没有真正意义上的 发送缓冲区. 调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后 续的传输动作; UDP具有接收缓冲区. 但是这个接收缓冲区不能保证收到的UDP报的顺序…

C语言天花板——指针(初阶)

&#x1f320;&#x1f320;&#x1f320; 大家在刚刚接触C语言的时候就肯定听说过&#xff0c;指针的重要性以及难度等级&#xff0c;以至于经常“谈虎色变”&#xff0c;但是今天我来带大家走进指针的奇妙世界。&#x1f387;&#x1f387;&#x1f387; 一、什么是指针&…

旋转角度对迭代次数的影响

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点&#xff0c;AB训练集各由5张二值化的图片组成&#xff0c;让A中有3个1&#xff0c;B中全是0&#xff0c;统计迭代次数并排序。 在3*5的空间内分布3个点有19种可能&#xff0c;但不同的分布只有6种 差值就诶够 …

七天学会C语言-第二天(数据结构)

1. If 语句&#xff1a; If 语句是一种条件语句&#xff0c;用于根据条件的真假执行不同的代码块。它的基本形式如下&#xff1a; if (条件) {// 条件为真时执行的代码 } else {// 条件为假时执行的代码 }写一个基础的If语句 #include<stdio.h> int main(){int x 10;…

硬件故障诊断:快速定位问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Linux基础开发工具使用快速上手

软件包管理器 概念理解 在Linux下安装软件的话&#xff0c;一个比较原始的办法是下载程序的源代码&#xff0c;然后进行编译&#xff0c;进而得到可执行程序&#xff0c;然后就可以运行这个软件了。但是这种做法太麻烦了&#xff0c;于是就有些人把一些常用的软件提前编译好&…

笔记1.5:计算机网络体系结构

从功能上描述计算机网络结构 分层结构 每层遵循某个网络协议完成本层功能 基本概念 实体&#xff1a;表示任何可发送或接收信息的硬件或软件进程。 协议是控制两个对等实体进行通信的规则的集合&#xff0c;协议是水平的。 任一层实体需要使用下层服务&#xff0c;遵循本层…

uniapp 小程序 父组件调用子组件方法

答案&#xff1a;配合小程序API > this.selectComponent("")&#xff0c;来选择组件&#xff0c;再使用$vm选择组件实例&#xff0c;再调用方法&#xff0c;或者data 1 设置组件的id,如果你的多端&#xff0c;请跟据情况设置ref,class,id&#xff0c;以便通过小…

一阶低通滤波器滞后补偿算法

一阶低通滤波器的推导过程和双线性变换算法请查看下面文章链接: PLC算法系列之数字低通滤波器(离散化方法:双线性变换)_双线性离散化_RXXW_Dor的博客-CSDN博客PLC信号处理系列之一阶低通(RC)滤波器算法_RXXW_Dor的博客-CSDN博客_rc滤波电路的优缺点1、先看看RC滤波的优缺点…

Redis 篇

1、为什么要用缓存&#xff1f; 使用缓存的目的就是提升读写性能。而实际业务场景下&#xff0c;更多的是为了提升读性能&#xff0c;带来更好的性能&#xff0c;带来更高的并发量。 Redis 的读写性能比 Mysql 好的多&#xff0c;我们就可以把 Mysql 中的热点数据缓存到 Redis…

Linux学习第14天:Linux设备树(一):枝繁叶茂见晴天

本节笔记主要学习了Linux设备树相关知识点&#xff0c;由于内容较多&#xff0c;打算分两天进行总结。今天着重学习Linux设备树&#xff0c;主要包括前三节内容&#xff0c;分别是概念、格式和语法。 本节思维导图内容如下&#xff1a; 一、什么是设备树 设备树可以用一个图来进…

Vivado XADC IP核 使用详解

本文介绍Vivado中XADC Wizard V3.3的使用方法。 XADC简介 XADC Wizard Basic Interface Options&#xff1a; 一共三种&#xff0c;分别是AXI4Lite、DRP、None。勾选后可在界面左侧看到相应通信接口情况。Startup Channel Selection Simultaneous Selection&#xff1a;同时监…

长胜证券:煤价突破900元大关 GLP-1减重药进入集中获批期

上星期五&#xff0c;两市股指早盘震动上扬&#xff0c;午后回落走低。到收盘&#xff0c;沪指跌0.28%报3117.74点&#xff0c;深成指跌0.52%报10144.59点&#xff0c;创业板指涨跌0.45%报2002.73点&#xff0c;科创50指数涨0.71%&#xff1b;两市合计成交7217亿元&#xff0c;…