LRU 缓存

news2024/12/23 15:02:12

题目链接

LRU 缓存

题目描述


注意点

  • 如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字
  • 函数 get 和 put 必须以 O(1) 的平均时间复杂度运行

解答思路

  • 如果想以O(1)的速度进行get,则需要将对应的key、value存到map中
  • 如果想以O(1)的速度进行put,又因为插入的时候可能由于空间已满需要将最久未使用的关键字,元素始终都在进行移动,所以需要使用链表来存储节点
  • 如果使用map存储key、value,链表中每个节点存储key、value,则在get某个节点需要将其移动到链表头部时查找该节点需要花费O(n)的时间,不满足题意,所以应该map存储的key为对应关键字的key,而存储的value应该是该key对应的链表节点

代码

class LRUCache {
    class DoublyLinkedList {
        int key;
        int value;
        DoublyLinkedList prev;
        DoublyLinkedList next;
        DoublyLinkedList() {}
        DoublyLinkedList(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    int size;
    DoublyLinkedList head;
    DoublyLinkedList tail;
    Map<Integer, DoublyLinkedList> map;

    public LRUCache(int capacity) {
        size = capacity;
        map = new HashMap<>(capacity);
        head = new DoublyLinkedList();
        tail = new DoublyLinkedList();
        head.next = tail;
        tail.prev = head;
    }
    
    public int get(int key) {
        DoublyLinkedList node = map.get(key);
        if (node == null) {
            return -1;
        }
        // 将该节点移动到链表头部
        removeNode(node);
        moveToHead(node);
        return node.value;
    }
    
    public void put(int key, int value) {
        DoublyLinkedList node = new DoublyLinkedList(key, value);
        // key在链表中已存在,只更新了value值,则直接对map进行更新即可,还要将新节点移动到链表头部
        if (map.containsKey(key)) {
            DoublyLinkedList oldNode = map.get(key);
            removeNode(oldNode);
            map.put(key, node);
            moveToHead(node);
            return;
        }
        // key在链表中不存在,且链表还有多余空间,则只需要将新节点插到链表头部
        if (map.size() < size) {
            moveToHead(node);
            map.put(key, node);
        } else {
            // key在链表中不存在,且链表已满,则需要删除链表尾,同时将新节点插到链表头部
            map.remove(tail.prev.key);
            removeNode(tail.prev);
            moveToHead(node);
            map.put(key, node);
        }
    }

    public void moveToHead(DoublyLinkedList node) {
        DoublyLinkedList tmp = head.next;
        head.next = node;
        node.prev = head;
        node.next = tmp;
        tmp.prev = node;
    }

    public void removeNode(DoublyLinkedList node) {
        DoublyLinkedList prevNode = node.prev;
        DoublyLinkedList nextNode = node.next;
        prevNode.next = nextNode;
        nextNode.prev = prevNode;
    }
}

关键点

  • map中存储的value为key对应的链表中的节点
  • 如果能成功get到值,则需要将该节点移动到链表的头部,移动时,还要删除链表中老位置的该节点
  • 在put时,如果此时链表和map中已经有该关键字,只是更新其value值,则需要更新其在链表中的节点值,同时将该节点移动到链表同步;如果没有该关键字但是链表空间足够,则只需要建一个新节点插到链表头部即可;如果没有该关键字且链表空间已满,则需要将尾部节点删掉,再将新节点插入到头部
  • 在增加和删除链表节点时同时也要对map中的相应值进行更新

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

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

相关文章

word 公式序号自动按章节排序

1.在普通视图下&#xff0c;使用Alt和F9切换到域代码模式。 普通视图 域代码模式 2.光标放在章节标题最后一个字后面&#xff0c;使用Ctrl和F9添加域代码的大括号 3.在大括号中键入 SEQ ch \h 4.光标放在刚刚的大括号后面&#xff0c;再次按下Ctrl和F9添加域代码的大括号 5.…

SAP MESSAGE ID LB31的问题和解决办法

外协采购订单判退时报错 EA 返回交货(原因)-> 3700006717 /00009 (0000) 1 EA 不正确过帐返回给供应商&#xff0c;错误信息:对所需数量 XXXXXX00003122&#xff0c;1.000 PCS 仍然未清LB 31 搜索到lb31是和批次相关的错误 https://www.michaelmanagement.com/sap-error-mes…

YoloX训练报错“IndexError: list index out of range”

问题描述 在训练Yolox时报错&#xff0c;IndexError: list index out of range 解决方案 在/yolox/data/datasets/voc.py修改第138行 (self._imgpath % self.ids[i]).split(self.root "\\")[1]修改完代码就没问题了&#xff0c;开始训练

48.循环类关键字 for in of while do continue break

我们使用循环的时候很可能出现一些问题&#xff0c;导致语句循环次数过多(几万次甚至几十万次)&#xff0c;这个时候请立即点击这里关闭选项卡 如果点关闭选项卡已经关不上了&#xff0c;可以立即结束浏览器进程&#xff0c;windows可以通过任务管理器关闭&#xff0c;linux可以…

华为OD机试真题 Java 实现【MELON的难题】【2023 B卷 100分】,采用动态规划算法,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、动态规划五、解题思路六、Java算法源码七、效果展示1、输入2、输出3、说明 大家好&#xff0c;我是哪吒。 做技术&#xff0c;我是认真的&#xff0c;立志于打造最权威的华为OD机试真题专栏&#xff0c;帮助那些与我有同样需求的…

【LeetCode热题100】打卡第35天:最小栈相交链表

文章目录 【LeetCode热题100】打卡第35天&#xff1a;最小栈&相交链表⛅前言 最小栈&#x1f512;题目&#x1f511;题解 相交链表&#x1f512;题目&#x1f511;题解 【LeetCode热题100】打卡第35天&#xff1a;最小栈&相交链表 ⛅前言 大家好&#xff0c;我是知识汲…

MySQL-分库分表详解(一)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xf…

C进阶:指针的进阶(1)

回归 哈喽哈喽大家好呀&#xff0c;我是灰灰快醒醒&#xff0c;时隔一个月又与大家见面了。众所周知&#xff0c;期末考试是中国教育部为大学生专门研发的一款开放式大逃杀游戏&#xff0c;学生需要扮演大难将至而绝望的人类&#xff0c;与小骚书共同完成《期末复习》的任务&a…

【无标题】采用技术外包做项目开发,不得不说的四大注意事项

在进行多项目开发及多个研发供应商团队管理&#xff08;技术外包管理&#xff09;时&#xff0c;你是不是也遇到不少问题。 项目管理者A&#xff1a;在项目开发中聘用外包技术团队的过程中&#xff0c;我踩过太多的坑&#xff0c;换过一批又一批的供应商&#xff0c;之前遇到过…

I.MX8MM系统构建 -- 1.系统烧录

硬件环境&#xff1a;米尔 MY8-C8MMX V1.3开发板软件工具&#xff1a;uuu烧录工具 环境准备 硬件环境 将开发板拨码开关调整为SW1(ON,OFF,x,x) SW2(x,x,x,x)&#xff0c;按照丝印字体方向向上为OFF&#xff0c;向下为ON。将开发板USB连接到PC给开发板通上12V电源(注意先修改拨…

Django框架之CSRF使用篇

Django框架之CSRF使用篇 目录 全局使用 设置csrf token 表单使用 脚本使用 单独豁免 引入csrf类库 设置单独豁免csrf 单独保护 关闭全局csrf 引入csrf库 设置函数保护 csrf token配置 总结 全局使用 Django项目配置中默认全局使用csrf中间件&#xff0c;注释掉即…

最新Jupyter Notebook(保姆级教程)

Jupyter Notebook介绍 什么是Jupyter Notebook Jupyter Notebook 是一个基于 Web 的交互式计算环境&#xff0c;支持多种编程语言&#xff0c;包括 Python、R、Julia 等。它的主要功能是将代码、文本、数学方程式、可视化和其他相关元素组合在一起&#xff0c;创建一个动态文…

STM32 Proteus仿真语音播报SGP30火灾报警器温度湿度-0072

STM32 Proteus仿真语音播报SGP30火灾报警器温度湿度-0072 Proteus仿真小实验&#xff1a; STM32 Proteus仿真语音播报SGP30火灾报警器温度湿度-0072 功能&#xff1a; 硬件组成&#xff1a;STM32F103C6单片机 0.960LED显示屏DHT11温度湿度电位器模拟SGP30二氧化碳传感器蜂鸣…

Layui实现动态树效果(书籍管理系统左侧下拉列表)

目录 一、前言 1.什么是树形菜单 2.树形菜单的使用场景 二、案例实现 1.需求分析 2.前期准备工作 ①导入依赖 ②工具类 BaseDao&#xff08;通用增删改查&#xff09; BuildTree(完成平级数据到父子级的转换) ResponseUtil&#xff08;将数据转换成json格式进行回显&…

1、Kubernetes 概述和架构

目录 一、基本介绍 二、kubernetes功能和架构 2.1、 概述 2.2 、功能 &#xff08;1&#xff09;自动装箱 &#xff08;2&#xff09;自我修复(自愈能力) &#xff08;3&#xff09;水平扩展 &#xff08;4&#xff09;服务发现 &#xff08;5&#xff09;滚动更新 &a…

磷铁环压脱机液压站比例阀放大器

冷轧热镀锌线液压系统比例阀放大器 热轧带钢步进梁式加热炉液压系统比例阀放大器 热轧带钢液压系统比例阀放大器 板坏连铸液压系统比例阀放大器 钢包精炼炉液压系统比例阀放大器 磷铁环压脱机液压站比例阀放大器 热轧带钢液压系统是一种用于热轧带钢生产的液压系统。它的…

校招失败后,在小公司熬了 2 年终于进了华为,竭尽全力....

其实两年前校招的时候就往华为投了一次简历&#xff0c;结果很明显凉了&#xff0c;随后这个理想就被暂时放下了&#xff0c;但是这个种子一直埋在心里这两年除了工作以外&#xff0c;也会坚持写博客&#xff0c;也因此结识了很多优秀的小伙伴&#xff0c;从他们身上学到了特别…

LiveGBS流媒体平台GB/T28181功能-支持UDP、TCP被动、TCP主动模式流传输模式之间有什么区别?

LiveGBS流媒体平台-国标流媒体服务几种流传输模式UDP、TCP被动、TCP主动模式区别是什么 1、背景1、GB28181流传输模式1.1、UDP1.2、TCP 被动1.3、TCP 主动 2、切换流传输模式2.1、编辑2.2、下拉切换 3、搭建GB28181视频直播平台 1、背景 国标GB28181协议中&#xff0c;视频流到…

什么是人工智能中的数据标注?

人工智能数据标注是对文本、视频、图像等元数据进行标注的过程&#xff0c;标记好的数据将用于训练机器学习的模型。常见的数据标注类型有文本标注、语义分割和图像视频标注。这些经标注的训练数据集可用于训练自动驾驶、聊天机器人、翻译系统、智能客服和搜索引擎等人工智能应…

LeetCode[239]滑动窗口最大值

难度&#xff1a;Hard 题目&#xff1a; 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff1a; 输入&#xf…