【数据结构】LRUCache|并查集

news2025/3/7 1:49:46

目录

一、LRUCache

1.概念

2.实现:哈希表+双向链表

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

🔥4.OJ练习

二、并查集

1. 并查集原理

2.并查集代码实现

3.并查集OJ


一、LRUCache

1.概念

最近最少使用的,一直Cache替换算法

LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法。 什么是Cache?狭义的Cache指的是位于CPU和主存间的快速RAM, 通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。 广义上的Cache指的是位于速度相差较大的两种硬件之间, 用于协调两者数据传输速度差异的结构。除了CPU与主存之间有Cache, 内存与硬盘之间也有Cache,乃至在硬盘与网络之间也有某种意义上的Cache── 称为Internet临时文件夹或网络内容缓存等。

Cache的容量有限,因此当Cache的容量用完后,而又有新的内容需要添加进来时, 就需要挑选并舍弃原有的部分内容,从而腾出空间来放新内容。LRU Cache 的替换原则就是将最近最少使用的内容替换掉。其实, LRU译成最久未使用会更形象, 因为该算法每次替换掉的就是一段时间内最久没有使用过的内容


2.实现:哈希表+双向链表

  • 哈希表:查找速度快O(1)
  • 双向链表:插入和删除的时间复杂度比较快O(1)
    • head
    • tail

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

  • initialCapacity:初始容量大小
  • loadFactor 加载因子
  • accessOrder
    • true:基于访问顺序 (把最常用的放到尾巴)
    • false:基于插入顺序

(1)当accessOrder的值为false的时候:

public static void main(String[] args) {
    Map<String, String> map = new LinkedHashMap<>(16,0.75f,false);
    map.put("1", "a");
    map.put("2", "b");
    map.put("4", "e");
    map.put("3", "c");
    System.out.println(map);
}

输出结果:

{1=a, 2=b, 4=e, 3=c}

以上结果按照插入顺序进行打印

(2) 当accessOrder的值为true的时候

public static void main(String[] args) {
    Map<String, String> map = new LinkedHashMap<>(16,0.75f,true);
    map.put("1", "a");
    map.put("2", "b");
    map.put("4", "e");
    map.put("3", "c");
    map.get("1");
    map.get("2");
    System.out.println(map);
}

输出结果:

{4=e, 3=c, 1=a, 2=b}

每次使用get方法,访问数据后,会把数据放到当前双向链表的最后。

当accessOrder为true时,get方法和put方法都会调用recordAccess方法使得最近使用的Entry移到双向链表的末尾;当accessOrder为默认值false时,从源码中可以看出recordAccess方法什么也不会做


🔥4.OJ练习

https://leetcode-cn.com/problems/lru-cache/

解法一:自己实现链表(最新在头/尾都可)

(1)get方法:存在否->存在需refresh

(2)put方法:是否存在->覆盖/创建

                        创建->还有空间否?

(3)refresh:删除+放到链表头部/尾部(注意:步骤4一定得在步骤1的后面

(4)delete:删除的是指定节点

class LRUCache {

    class DLinkNode {
        public int key;
        public int val;

        public DLinkNode prev;
        public DLinkNode next;

        public DLinkNode(int key,int val) {
            this.key = key;
            this.val = val;
        }
    }

    public DLinkNode head;
    public DLinkNode tail;
    public Map<Integer,DLinkNode> map;
    public int n;

    public LRUCache(int capacity) {
        this.head = new DLinkNode(-1,-1);
        this.tail = new DLinkNode(-1,-1);
        head.next = tail;
        tail.prev = head;
        map = new HashMap<>();
        this.n = capacity;
    }

    public int get(int key) {
        if(map.containsKey(key)) {
            DLinkNode node = map.get(key);
            refresh(node);
            return node.val;
        }
        return -1;
    }

    public void put(int key, int value) {
        DLinkNode node = null;
        if(map.containsKey(key)) {
            //存在->覆盖
            node = map.get(key); //直接在node上改,因为要refresh
            node.val = value;
        } else {
            //还有空间否
            if(map.size() == n) {
                DLinkNode del = tail.prev;//这里得记录下来,不然删了,另一个就删不了
                map.remove(del.key);
                delete(del);
            }
            //放入map
            node = new DLinkNode(key,value);
            map.put(key,node);
        }
        refresh(node);
    }

    //放到链表头部(删除+放置)
    public void refresh(DLinkNode node) {
        delete(node);//删除指定节点
        node.next = head.next;
        head.next.prev = node;
        node.prev = head;
        //这个步骤4一定得在1的后面
        head.next = node;

    }

    //删除指定节点
    public void delete(DLinkNode node) {
        if(node.prev != null ) {
            DLinkNode pre = node.prev;
            pre.next = node.next;
            node.next.prev = pre;
        }
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

解法二:

class LRUCache extends LinkedHashMap<Integer, Integer>{
private int capacity;

public LRUCache(int capacity) {
    /**
    第3个参数的意思:
    当accessOrder设置为false时,会按照插入顺序进行排序,当accessOrder为true是,会按照访问顺 序(也就是插入和访问都会将当前节点放置到尾部,尾部代表的是最近访问的数据,这和JDK1.6是反过来 的,jdk1.6头部是最近访问的)。
    */
    super(capacity,0.75F,true);
    this.capacity = capacity;
} 

//此时的get方法一定会,返回最近访问的数据
public int get(int key) {
    return super.getOrDefault(key, -1);
}

public void put(int key, int value) {
    super.put(key, value);
} 

//必须重写这个方法,默认是false。此时根据
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
    }
}
public class TestDemo {
    public static void main(String[] args) {
        LRUCache lruCache = new LRUCache(3);
        //尾插法插入
        lruCache.put(2,1);
        lruCache.put(3,1);
        lruCache.put(4,1);
        System.out.println(lruCache);//{2=1, 3=1, 4=1}
        System.out.println(lruCache.get(2));//1 并且放到链表的尾巴
        System.out.println(lruCache);//{ 3=1, 4=1,2=1}
    }
} 

/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache* obj = new LRUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/

二、并查集

1. 并查集原理

(1)解决的问题

  • 将n个不同的元素划分成一些不相交的集合,开始时,每个元素自己都是单元素集合,然后按照一定的规律将归于同一组元素的集合合并
  • 这个过程需要反复用到查询某个元素归属哪个集合的运算

(2)具体例子理解

  • 初始状态


    某公司今年校招全国总共招生10人,西安招4人,成都招3人,武汉招3人,10个人来自不同的学校,起先互不相识,每个学生都是一个独立的小团体,现给这些学生进行编号
  • 集合树形表示


    西安学生小分队s1={0,6,7,8},成都学生小分队s2={1,4,9},武汉学生小分队s3={2,3,5}就相互认识了,10个人形成了三个小团体。假设右三个群主0,1,2担任队长
  • 并查集表示

    • 数组的下标:表示对应集合中元素的编号
    • 数组元素如果是负数:负数代表根节点,数字代表这个集合中元素的个数
    • 数组如果是非负数:代表该元素的双亲在数组中的下标
  • 合并1和8


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

(3)小结:并查集解决的问题

  • 查找元素属于哪个集合
    沿着数组表示树形关系以上一直找到根(即:树中中元素为负数的位置)
  • 查看两个元素是否属于同一个集合
    沿着数组表示的树形关系往上一直找到树的根,如果根相同表明在同一个集合,否则不在
  • 将两个集合归并成一个集合
    将一个集合加入另一个集合 ,同时数组的下标也需要修改
  • 集合的个数
    数组中元素为负数的个数即为集合的个数

2.并查集代码实现

  • (1)查找x元素的根节点

  • (2)查询x1和x2是不是同一个集合

  • (3)合并x1和x2的根节点的两个集合(x2并入x1

  • (4)当前集合的个数(不是元素的个数)


3.并查集OJ

  • 省份数量
  • 等式方程的可满足性

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

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

相关文章

初识Qt · 信号与槽 · 基础知识

目录 前言&#xff1a; 信号和槽初识 两个问题 前言&#xff1a; 本文我们正式开始介绍信号与槽这个概念&#xff0c;在谈及Qt中的信号与槽这个概念之前&#xff0c;我们不妨回顾一下Linux中的信号&#xff0c;比如发生了除0错误&#xff0c;OS就会给该进程发送一个信号&am…

Java高频面试之集合-03

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;说说ArrayList和LinkedList的区别 ArrayList 与 LinkedList 的详细对比 一、底层数据结构 特性ArrayListLinkedList存…

宇树科技再落一子!天羿科技落地深圳,加速机器人创世纪

2025年3月5日&#xff0c;机器人行业龙头宇树科技&#xff08;Unitree&#xff09;在深圳再添新动作——全资子公司深圳天羿科技有限公司正式成立。这家注册资本10万元、法定代表人周昌慧的新公司&#xff0c;聚焦智能机器人研发与销售&#xff0c;标志着宇树科技在华南市场的战…

【长安大学】苹果手机/平板自动连接认证CHD-WIFI脚本(快捷指令)

背景&#xff1a; 已经用这个脚本的记得设置Wifi时候&#xff0c;关闭“自动登录” 前几天实在忍受不了CHD-WIFI动不动就断开&#xff0c;一天要重新连接&#xff0c;点登陆好几次。试了下在网上搜有没有CHD-WIFI的自动连接WIFI自动认证脚本&#xff0c;那样我就可以解放双手&…

计算机毕业设计SpringBoot+Vue.js电商平台(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

【杂谈】信创电脑华为w515(统信系统)登录锁定及忘记密码处理

华为w515麒麟芯片版&#xff0c;还有非麒麟芯片版本&#xff0c;是一款信创电脑&#xff0c;一般安装的UOS系统。 准备一个空U盘&#xff0c;先下载镜像文件及启动盘制作工具&#xff0c;连接如下&#xff1a; 百度网盘 请输入提取码 http://livecd.uostools.com/img/apps/l…

初始提示词(Prompting)

理解LLM架构 在自然语言处理领域&#xff0c;LLM&#xff08;Large Memory Language Model&#xff0c;大型记忆语言模型&#xff09;架构代表了最前沿的技术。它结合了存储和检索外部知识的能力以及大规模语言模型的强大实力。 LLM架构由外部记忆模块、注意力机制和语…

Vue+el-upload配置minIO实现大文件的切片并发上传、上传进度展示、失败重试功能

vue3el-upload实现切片上传 效果图 初始界面 上传中的界面 上传完成的界面 上传失败的界面 <template><div><el-uploadclass"BigFileUpload"ref"uploadRef"action"#"drag:show-file-list"false":on-change"…

正则表达式梳理(基于python)

正则表达式&#xff08;regular expression&#xff09;是一种针对字符串匹配查找所定义的规则模式&#xff0c;独立于语言&#xff0c;但不同语言在实现上也会存在一些细微差别&#xff0c;下面基于python对常用的相关内容进行梳理。 文章目录 一、通用常识1.通配符ps.反义 2.…

【仿muduo库one thread one loop式并发服务器实现】

文章目录 一、项目介绍1-1、项目总体简介1-2、项目开发环境1-3、项目核心技术1-4、项目开发流程1-5、项目如何使用 二、框架设计2-1、功能模块划分2-1-1、SERVER模块2-1-2、协议模块 2-2、项目蓝图2-2-1、整体图2-2-2、模块关系图2-2-2-1、Connection 模块关系图2-2-2-2、Accep…

服务流程设计和服务或端口重定向及其websocket等应用示例

服务流程设计和服务或端口重定向及其websocket等应用示例 目录 服务或端口重定向的服务设计和websocket等应用示例 一、通用请求控制流程 1.1、入口 1.2、所有GET请求首先预检控制单元 1.3、http请求会分别自动307重定向 1.4、所有请求首先执行跨源控制单元 1.5、然后…

【数据库】关系代数

关系代数 一、关系代数的概念二、关系代数的运算2.1 并、差、交2.2 投影、选择2.3 笛卡尔积2.4 连接2.5 重命名2.6 优先级 一、关系代数的概念 关系代数是一种抽象的数据查询语言用对关系的运算来表达查询 运算对象&#xff1a;关系运算符&#xff1a;4类运算结果&#xff1a;…

ubuntu20 安装python2

1. 确保启用了 Universe 仓库 在某些情况下&#xff0c;python2-minimal 包可能位于 Universe 仓库中。你可以通过以下命令启用 Universe 仓库并更新软件包列表&#xff1a; bash复制 sudo add-apt-repository universe sudo apt update 然后尝试安装&#xff1a; bash复制…

MySQL无法连接到本地localhost的解决办法2024.11.8

问题描述&#xff1a;我的MySQL可以远程连接服务器&#xff0c;但无法连接自己的localhost。 错误提示&#xff1a; 2003 - Cant connet to MySQL server on localhost(10061 "Unknown error")查找问题原因&#xff1a; 1. 检查环境变量是否正确&#xff1a;发现没…

最新Spring Security实战教程(一)初识Spring Security安全框架

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…

告别GitHub连不上!一分钟快速访问方案

一、当GitHub抽风时&#xff0c;你是否也这样崩溃过&#xff1f; &#x1f621; npm install卡在node-sass半小时不动&#x1f62d; git clone到90%突然fatal: early EOF&#x1f92c; 改了半天hosts文件&#xff0c;第二天又失效了... 根本原因&#xff1a;传统代理需要复杂…

Leetcode 1477. 找两个和为目标值且不重叠的子数组 前缀和+DP

原题链接&#xff1a; Leetcode 1477. 找两个和为目标值且不重叠的子数组 class Solution { public:int minSumOfLengths(vector<int>& arr, int target) {int narr.size();int sum0;int maxnINT_MAX;vector<int> dp(n,maxn);//dp[i]表示以索引i之前的满足要求…

R语言绘图:韦恩图

韦恩分析 韦恩分析&#xff08;Venn Analysis&#xff09;常用于可视化不同数据集之间的交集和并集。维恩图&#xff08;Venn diagram&#xff09;&#xff0c;也叫文氏图、温氏图、韦恩图、范氏图&#xff0c;用于显示元素集合重叠区域的关系型图表&#xff0c;通过图形与图形…

智谱AI-FunctionCall

智谱AI-FunctionCall 编写FuncationCall大模型的函数调用&#xff0c;先直观的感受一下的感受下FunctionCall的魅力 文章目录 智谱AI-FunctionCall[toc]1-参考网址2-思路整理3-代码拆件1-[非核心]两个业务函数2-[非核心]业务函数的JsonSchema定义3-[核心]FunctionCall的调用1-打…

android亮灭屏流程分析

前言 亮灭涉及的东西非常多&#xff0c;因此单独写一个文档&#xff0c;进行详细说明&#xff0c;亮灭屏包括的东西不只是亮灭屏&#xff0c;还包括亮度调节、屏幕状态变化等东西。本文仅作学习使用&#xff0c;不涉及商业&#xff0c;侵权请联系删除。 framework层的学习链接…