并查集和LRUCache

news2024/12/28 4:05:25

目录

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;

    }
    @Override
    public Integer get(Object key) {
        return super.getOrDefault(key,-1);
    }

    @Override
    public Integer put(Integer key, Integer value) {
        return super.put(key, value);
    }

    @Override
    protected 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;
        }

        @Override
        public 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.coloradmin.cn/o/706260.html

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

相关文章

OSGI-Bundle:概念和入门

OSGI(Open Service gateway initactive)是java动态化模块系统的一系列规范。即一个系统应用上可以有很多可插拔的小应用&#xff0c;整个应用能运行和协调&#xff0c;小应用之间也可以相互交互完成业务需求。 Bundle: bundle 是以 jar 包形式存在的一个模块化物理单元&#x…

Ceph:关于 Ceph 用户认证授权管理的一些笔记

写在前面 准备考试&#xff0c;整理 Ceph 相关笔记博文内容涉及, Ceph 用户管理&#xff0c;认证管理&#xff0c;权限管理 以及相关 Demo理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&…

antdesginVue a-date-picker(日期时间选择器)禁用当前时间之前的时间,包含时分秒

antdesginVue a-date-picker(日期时间选择器)禁用当前时间之前的时间&#xff0c;包含时分秒 话不多说直接上效果 <a-form-item label"发生时间" name"start_time"><a-date-pickerstyle"width: 100%"allowClearv-model:value"f…

C++模板进阶知识

文章目录 前言模板进阶1.非类型模板参数2.模板的特化2.1概念2.2函数模板特化2.3类模板特化2.3.1 全特化2.3.2 偏特化2.3.3 类模板特化应用示例 3.模板的分离编译3.1 什么是分离编译3.2 模板的分离编译3.3 解决方法 4 模板总结 后记 前言 之前我们讲过模板初阶的知识&#xff0…

Linux 解决root用户被限制连接服务器

Linux 解决root用户被限制连接服务器 1. 问题描述2. 解决问题2.1 方式一&#xff08;忘记root密码的情况&#xff09;2.2 方式二&#xff08;知道root密码的情况&#xff09; 3. 其他 1. 问题描述 使用 root 用户不能链接服务器&#xff0c;密码对&#xff0c;就是连接不上&am…

uniapp:分享一个自定义侧滑样例

首先看html,分为两部分&#xff0c;主体内容部分和功能部分&#xff0c;功能部分在css中定位到主体部分的右边 <view class"section" ref"box_center" touchstart"drawStart" touchmove"drawMove($event)"touchend"drawEnd($…

晨控智能UWB室内定位:工厂智能化的新引擎

晨控智能UWB室内定位&#xff1a;工厂智能化的新引擎 工厂是一个复杂而庞大的环境&#xff0c;通常包括多个车间、设备、人员以及大量的物料和产品。需要实时、准确的定位数据来支持各项运营活动。然而&#xff0c;传统的定位技术无法满足工厂内部的高精度定位需求。而UWB室内…

u-boot的烧写及使用,u-boot-2013.01的移植 6.30

1.将Linux的执行文件放到板子上运行 嵌入式系统 1.嵌入式系统 定制2.硬件&#xff1a;核心芯片底板软件&#xff1a;驱动应用 驱动系统应用&#xff08;并发&#xff0c;网络&#xff0c;文件。。。&#xff09;3.系统&#xff1a;linux 开源 模块化 支持芯片众多 功能…

针对字符串输入之间有空格的问题相关的问题

先说结论&#xff1a; bool flag true;while (cin >> s) {if (flag) {flag false;cout << s.size();} else {cout << , << s.size();}} 即用while&#xff08;cin>>s&#xff09;来输入&#xff0c;一段单词一段单词的来做&#xff08;遇到ci…

第十一章 原理篇:transformer模型入门

说在前面的话&#xff1a; 找工作面试不是特别顺利。进了目标公司的二面&#xff0c;但是一面面试官问的一些“新技术”问题答得不太好&#xff0c;尤其是transformer相关的。这一点确实是自己的问题&#xff0c;在工作后总是面向业务学习&#xff0c;对很多算法都是处于“听说…

AD从原理图到PCB超详细教程

AD超详细教程 前言一、建立一个工程模板二、原理图1.设计原理图。2.使用AD自带库和网上开源原理图库3.画原理图库4.编译原理图 三、PCB1.确定元器件尺寸大小2.绘制PCB Library①使用元器件向导绘制元件库②原理图与PCB的映射 3.绘制PCB①更新PCB②调整元件位置③布线④漏线检查…

库操作和表操作(数据库系列2)

目录 前言&#xff1a; 1.数据库的操作 1.1显示当前的数据库 1.2创建数据库 1.3使用数据库 1.4删除数据库 2.常用数据类型 2.1数值类型 2.2字符串类型 2.3日期类型 3.表的操作 3.1查看表结构 3.2创建表 3.3查看表 3.4删除表 结束语&#xff1a; 前言&#xff1…

【硬件自动化测试--测试软件的设计及实现】如何设计并实现!

今天来聊聊关于硬件方向的自动化软件设计及实现,后面我会用实例来让我们更加深入的了解硬件自动化,首先开发工具选择的是python语言,为啥选择python语言呢,因为他的语法比较简洁,外置库非常多,反正就是对于做自动化方面很实用就对了。 1.硬件自动化测试大致分为三个阶段实…

拓展:IDEA如何使用不同版本的JDK?(改了还报错很可能因为没改全,以mac为例)

以下面的案例为例 Enhanced ‘switch’ blocks are not supported at language level ‘8’ 后面知道是因为Spring的版本和JDK的版本不对应&#xff0c;结果网上找到的解决方案都很简单。下载了一个新版本的JDK&#xff0c;然后IDEA里面Project Structure的Project标签里把SDK给…

ubuntu的aarch64版本上安装anaconda

ubuntu的aarch64版本上安装anaconda 问题背景&#xff1a;今天在基于docker安装的ubuntu18-04的版本上想要安装anaconda&#xff0c;但是出现了问题&#xff0c;发现ubuntu的版本18-04对应的是aarch64&#xff0c;因此记录安装方法。 首先下载安装包没问题但是&#xff0c;在具…

机器学习复习7

机器学习复习7 1 - 根据下图中绘制的决策树&#xff0c;如果一个动物的耳朵是软的&#xff0c;脸型是圆的&#xff0c;并且有胡须&#xff0c;那么这个模型会预测它是猫还是不是猫&#xff1f; A. 不是猫 B. 是猫 **答案&#xff1a;B ** 2 - 以一棵决策树学习来对垃圾邮件和非…

spring boot启动原理分析

springboot启动类中有两个关键的地方 1.SpringBootApplication注解 2.SpringApplication.run方法 SpringBootApplication注解分析 SpringBootApplication注解由三大注解构成&#xff0c; SpringBootConfiguration、EnableAutoConfiguration、ComponentScan。 SpringBootCon…

Java-八股文-基础本部分<一>

Java基础部分 基础篇<一> Java基础部分 基础篇<二> Java基础部分 基础篇<三> Java基础部分 异常篇 Java基础部分 集合篇 Java基础部分 线程篇 ❤️ &#x1f9e1; &#x1f49b; &#x1f49a; &#x1f499; &#x1f49c;&#x1f5a4; &#x1f90d;…

什么是网络货运平台?

一、什么是网络货运平台&#xff1f; 网络货运平台是依托互联网平台整合配置运输资源&#xff0c;以承运人身份与托运人签订运输服务合同、承担承运人责任&#xff0c;委托实际承运人完成运输服务的物流平台。它通过互联网形式实现运输过程真实、公平、公正、合法&#xff0c…

【LeetCode】239. 滑动窗口最大值

239. 滑动窗口最大值 思路 当我们遍历数组时&#xff0c;我们需要维护一个双端队列&#xff0c;用于存储滑动窗口中的元素的索引。 队列中的元素按照降序排列&#xff0c;即「队头元素是当前滑动窗口中的最大值」。 具体的步骤如下&#xff1a; 创建一个双端队列 window&#…