并查集和LRUCache

news/2024/11/25 19:39:37/

目录

1. 并查集

1.1原理

1.2实现

1.3应用

1.3.1省份数量

1.3.2等式方程的可满足性

2.LRUCache

1.概念

2.实现

 3.JDK中类似LRUCahe的数据结构LinkedHashMap

4.LRU Cache的OJ


1. 并查集

1.1原理

把不同的元素划分到不想交的集合.开始时,每个元素自成一个单元集合,然后按照规律把是同一组的元素集合合并

s1={0,6,7,8},s2={1,4,9},s3={2,3,5}

 结论:

        1.元素下标对应集合中元素的编号   例如:array[8]的值0是8的父亲

        2.如果有负号,负号代表根,数字代表集合的元素个数

        3.如果为非负数,为父亲在数组的下标

问题:

        1.查找元素属于哪个集合

                根据数组表示的树形关系找根

        2. 查看两个元素是否属于同一个集合

                根据数组表示的树形关系找根,如果根相同表示在同一个集合

        3. 将两个集合归并成一个集合

                A集合改为B集合的名称,B集合数为两个集合数数之和

         4. 集合的个数

                遍历数组,数组中元素为负数的个数即为集合的个数

1.2实现

public class UnionFindSet {public int[] elem;public  UnionFindSet(int n){this.elem=new int[n];Arrays.fill(elem,-1);}//找根public int findRoot(int x){if(x<0){throw  new IndexOutOfBoundsException();}while(elem[x]>0){//值为负数为根x=elem[x];}return x;}//判断是不是一个集合public boolean isSame(int x1,int x2){int index1=findRoot(x1);int index2=findRoot(x2);return index1==index2 ? true :false;}//合并public void union(int x1,int x2){int index1=findRoot(x1);int index2=findRoot(x2);if(index1==index2) return;elem[index1]=elem[index1]+elem[index2];elem[index2]=index1;}//根的个数public int getCount(int x){int count=0;for(int s:elem){if(s<0){count++;}}return count;}public void print(){for(int x:elem){System.out.print(x+" ");}System.out.println();}
}

1.3应用

1.3.1省份数量

 把为1的合并,输出集合的个数

class Solution {public int findCircleNum(int[][] isConnected) {int len=isConnected.length;UnionFindSet union=new UnionFindSet(len);for(int i=0;i<isConnected.length;i++){for(int j=0;j<isConnected[0].length;j++){if(isConnected[i][j]==1){union.union(i,j);}}}return union.getCount();}
}
class UnionFindSet{public int[] elem;public UnionFindSet(int n){this.elem=new int[n];Arrays.fill(elem,-1);}//找根节点public int find(int x){if(x < 0) {throw new IndexOutOfBoundsException("下标不合法,是负数");}while(elem[x]>=0){x=elem[x];}return x;}//是否在一个集合public boolean isSame(int x1,int x2){int index1=find(x1);int index2=find(x2);return index1==index2 ?true :false;}//合并public void union(int x1,int x2){int index1=find(x1);int index2=find(x2);if(index1==index2) return ;elem[index1]=elem[index1]+elem[index2];elem[index2]=index1;}//个数public int getCount(){int count=0;for(int i:elem){if(i<0){count++;}}return count;}
}

1.3.2等式方程的可满足性

 把是==的两个放到一个集合,检查!=两个的是否在一个集合,如果不在==>满足

class Solution {public boolean equationsPossible(String[] equations) {UnionFindSet UnionFindSet=new UnionFindSet(26);for(int i=0;i<equations.length;i++){if(equations[i].charAt(1)=='='){UnionFindSet.unoin(equations[i].charAt(0)-'a',equations[i].charAt(3)-'a');}}for(int i=0;i<equations.length;i++){if(equations[i].charAt(1)=='!'){int root1=  UnionFindSet.find(equations[i].charAt(0)-'a');int root2= UnionFindSet.find(equations[i].charAt(3)-'a');if(root1==root2){return false;}}}return true;
}
}public class UnionFindSet {public int[] elem;public UnionFindSet(int n){this.elem=new int[n];Arrays.fill(elem,-1);}//找根public int find(int x){if(x<0){throw new IndexOutOfBoundsException("下标不合法,是负数");}while(elem[x]>=0){x=elem[x];}return x;}//是不是在一个集合public boolean isSame(int x1,int x2){int index1=find(x1);int index2=find(x2);return index1==index2 ?true:false;}//合并public void unoin(int x1,int x2){int index1=find(x1);int index2=find(x2);if(index1==index2) return;elem[index1]=elem[index1]+elem[index2];elem[index2]=index1;}
}

2.LRUCache

1.概念

一种Cache替换算法,把最近少使用的内容替换掉

2.实现

用双向链表和哈希表搭配

双向链表可以实现任意位置O(1)的插入和删除,使用哈希表是因为哈希表(快速定位)的增删查改也是O(1)。

 3.JDK中类似LRUCahe的数据结构LinkedHashMap

参数说明:

1. initialCapacity 初始容量大小,使用无参构造方法时,此值默认是16

2. loadFactor 加载因子,使用无参构造方法时,此值默认是 0.75f

3. accessOrder false: 基于插入顺序 true: 基于访问顺序

示例1:当值为false的时候 基于插入顺序

LinkedHashMap<String,Integer> linkedHashMap=new LinkedHashMap<String,Integer>(16, (float) 0.7,false);
linkedHashMap.put("mq",1);
linkedHashMap.put("haha",11);
linkedHashMap.put("hello",12);
System.out.println(linkedHashMap);
System.out.println("获取元素");
System.out.println(linkedHashMap.get("haha"));
System.out.println(linkedHashMap);

 示例2:当值为true的时候 基于访问顺序

LinkedHashMap<String,Integer> linkedHashMap=new LinkedHashMap<String,Integer>(16, (float) 0.7,true);
linkedHashMap.put("mq",1);
linkedHashMap.put("haha",11);
linkedHashMap.put("hello",12);
System.out.println(linkedHashMap);
System.out.println("获取元素");
System.out.println(linkedHashMap.get("haha"));
System.out.println(linkedHashMap);

 访问过的放到尾部

4.LRU Cache的OJ

public class LRUCache extends  LinkedHashMap<Integer,Integer>{public int capacity;LRUCache(int capacity){//true基于访问顺序super(capacity,0.75f,true);this.capacity=capacity;}@Overridepublic Integer get(Object key) {return super.getOrDefault(key,-1);}@Overridepublic Integer put(Integer key, Integer value) {return super.put(key, value);}@Overrideprotected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {return size()>capacity;}
}
public class LRUCache {static class DLinkNode{public  int key;public int val;public DLinkNode prev;public DLinkNode next;public DLinkNode(){}public DLinkNode(int key,int val){this.key=key;this.val=val;}@Overridepublic String toString() {return "{ key=" + key + ", val=" + val+"} ";}}public  DLinkNode head;public DLinkNode tail;public  int usedSize;//有效数据个数public Map<Integer,DLinkNode>   cache;public int capacity;//默认容量public  LRUCache(int capacity){this.head=new DLinkNode();this.tail=new DLinkNode();head.next=tail;tail.prev=head;cache=new HashMap<>();this.capacity=capacity;}/*** 存储元素* 1.查找是否存储过* 2.没有* 2.1 实例化结点* 2.2 存储到map中* 2.3 将该结点移动到尾结点(新插入的)* 2.4 检查当前有效个数是不是超过capacity* 2.5 超过,去掉头结点* 2.6 清除缓存中的元素* 2.7 usedSize--* 3.有* 3.1 更新key对应的val* 3.2 将该结点移动到尾结点(新插入的)* @param key* @param val*/public  void  put(int key,int val){DLinkNode node=cache.get(key);if(node==null){DLinkNode dLinkNode=new DLinkNode(key,val);cache.put(key,dLinkNode);addToTail(dLinkNode);usedSize++;if(usedSize>capacity){DLinkNode dLinkNode1=removeHead();cache.remove(dLinkNode1.key);//清除usedSize--;}}else{node.val=val;moveToTail(node);}}/*** 移除当前结点到尾结点*/private void moveToTail(DLinkNode node) {//1.删除node.prev.next=node.next;node.next.prev=node.prev;//2.加到尾部addToTail(node);}/*** 插入到尾结点* @param node*/private void addToTail(DLinkNode node){tail.prev.next=node;node.prev=tail.prev;node.next=tail;tail.prev=node;}/*** 移除第一个结点* @return*/private DLinkNode removeHead(){DLinkNode del=head.next;head.next=del.next;del.next.prev=head;return del;}/*** 把访问的结点放到尾巴* @return*/public int get(int key){DLinkNode node=cache.get(key);if(node==null){return -1;}moveToTail(node);return node.val;}
}


http://www.ppmy.cn/news/722674.html

相关文章

如何在 React 中进行静态类型检查

PropTypes React自带了一个名为PropTypes的库&#xff0c;可以用于定义组件的属性类型。通过在组件中定义PropTypes&#xff0c;可以对传入组件的属性进行类型检查。PropTypes提供了一些内置的类型检查器&#xff0c;如string、number、bool、array、object等&#xff0c;还可…

双android系统pcb整合,基于Android的大屏幕拼接显示系统研究与实现

摘要&#xff1a; 近几年随着社会经济的发展,液晶拼接显示大屏幕凭借大屏,清晰度高,使用寿命长,可724小时长时间连续显示等优点满足各行业公共显示的需求,但是其大多数产品不具有智能操作系统,在多媒体播放和软件升级功能上显得薄弱.本文运用成熟的Android方案结合视频处理芯片…

关于NVIDIA使用多屏幕拼接时,全屏无法铺满所有屏幕解决办法

使用NVIDIA拼接多个屏幕时&#xff0c;最大化应用后无法铺满所有屏幕的解决办法&#xff1a; 1.桌面右键打开NVIDIA控制面板 2.在顶部工具栏打开桌面 3.依次打开桌面-》surround显示器 4.将“最大化跨越所有显示器窗口”选项勾选后完美解决

ubuntu如何连接显示器

转载 https://blog.csdn.net/qq_24946843/article/details/93593078

HP服务器连接显示器怎么连,笔记本如何外接显示器 外接显示器连接步骤【详解】...

笔记本如何外接显示器? 从广义上讲&#xff0c;街头随处可见的大屏幕、电视机、BSV液晶拼接的荧光屏、手机和快译通等的显示屏都算是显示器的范畴&#xff0c;一般指与电脑主机相连的显示设备。 下面&#xff0c;我们就来看看电脑连接电视的详细步骤。 连接数据线 1、首先准备…

linux qt多屏幕输出,Qt5 多显示器获取不同显示器的分辨率和位置的方法

Qt5 多显示器获取不同显示器的分辨率和位置的方法 先放官方文档链接:QDesktopWidget - Qt5 Reference 之前一直在用被我乱搞后的ShadowPlayer作为默认播放器,后来主力系统换成linux了也就没再用了。这两天the Witness发布,也正好想玩一些别的windows only的游戏,于是回到wi…

ubuntu12.04双屏拼接

Ctrl Alt F1&#xff0c;以本人的用户名和密码登录后&#xff0c;关闭X Server:sudo /etc/init.d/lightgm stop运行命令&#xff1a;sudo X -configure, 这样&#xff0c;在当前用户的目录下就会生成一个xorg.conf.new文件重新启动X server&#xff0c;sudo /etc/init.d/ligh…

【基于NSR3588开发板Android12三屏拼接显示实例】

基于NSR3588开发板Android12三屏拼接显示实例 1.硬件接口 2路HDMI接口 1路Type-c DP转HDMI 如下图&#xff1a; 2.多屏显示拼接简介 RK3588可以支持如下多种拼接模式&#xff1a; 我们采用水平3x1的方式&#xff0c;接3个1920x1080的HDMI 显示输出。 总分辨率为&#xff…