【LeetCode】【算法】146. LRU缓存

LeetCode - 146.LRU缓存

题目描述

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity)以正整数作为容量capacity初始化 LRU 缓存
int get(int key)如果关键字key存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value)如果关键字key已经存在,则变更其数据值value;如果不存在,则向缓存中插入该组key-value 。如果插入操作导致关键字数量超过capacity,则应该逐出最久未使用的关键字。
函数get和put必须以 O(1) 的平均时间复杂度运行。

实现思路

LRU本质就是通过一个队列实现的,对于put函数和get函数,最特别的地方在于访问时需要将访问的节点挪到队尾。

  1. 创建ListNode以实现节点。其中包含int key, int value, ListNode next, ListNode prev(双向指针的实现)
  2. 在LRU类中的属性包括:
    I. 虚拟头尾节点ListNode dummyHead, dummyTail;
    II. HashMap用于以O(1)平均复杂度访问到目标节点Map<Integer, ListNode> map;(如果需要遍历整个链表来找目标节点,就不是O(1)的复杂度了)
    III. int capacity表示链表的容量,这是题目需要指定的
    IV. int listLen用于记录当前链表的长度
  3. 初始化LRU类,就是对上面的这些属性做一个初始化,记得虚拟头尾节点的next属性和prev属性需要相连
  4. put方法思路:
    I. 使用map来检查这个节点是否在链表中;
    ① 如果在链表中,则通过map得到这个节点,将该节点从链表中删除,并给改节点赋予新的值;
    ② 如果不在链表中,又分为listLen>=capacitylistLen<capacity的情况(也就是链表容量是否超过指定容量了)
    情况1:链表当前容量已经达到了指定容量,需要删除最久未访问节点(队头),使用虚拟头结点dummyHead来做删除;根据给定的key和value新建一个节点
    情况2:链表当前容量未达到指定容量,则链表长度++,根据给定的key和value新建一个节点
    II. 利用dummyTail将该节点放到链表的最后,并更新map中的内容
  5. get方法思路:
    I. 使用map来检查这个节点是否在链表中,不在返回-1;
    II. 否则利用map来拿到这个节点,将它从链表中移除;并利用dummyTail将该节点放到链表最后,返回该节点的值

实现代码

class LRUCache {

    class ListNode{
        int key;
        int value;
        ListNode next;
        ListNode prev;

        public ListNode() {

        }

        public ListNode(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    ListNode dummyHead;
    ListNode dummyTail;
    Map<Integer, ListNode> map;
    int capacity;
    int listLen;

    public LRUCache(int capacity) {
        map = new HashMap<>();
        dummyHead = new ListNode();
        dummyTail = new ListNode();
        dummyHead.next = dummyTail;
        dummyTail.prev = dummyHead;
        this.capacity = capacity;
        this.listLen = 0;
    }

    public void put(int key, int value) {
        ListNode listNode = null;
        // 如果map里面没有这个key
        if (!map.containsKey(key)){
            // 如果长度已经满了,就移除一个
            if (listLen >= capacity){
                ListNode removeNode = dummyHead.next;
                removeNode.next.prev = removeNode.prev;
                removeNode.prev.next = removeNode.next;
                map.remove(removeNode.key);
            } else {
                listLen++;
            }
            // 新增一个
            listNode = new ListNode(key, value);
        }
        // 如果map里有这个key
        else {
            listNode = map.get(key);
            // 把这个listNode从链表上删除
            ListNode prev_node = listNode.prev;
            ListNode next_node = listNode.next;
            prev_node.next = next_node;
            next_node.prev = prev_node;
            listNode.value = value;
        }
        // 把这个listNode弄到后面去
        ListNode insertPre = dummyTail.prev;
        insertPre.next = listNode;
        listNode.prev = insertPre;
        listNode.next = dummyTail;
        dummyTail.prev = listNode;
        map.put(key, listNode);
    }

    public int get(int key) {
        if (!map.containsKey(key)){
            return -1;
        } else {
            int result = map.get(key).value;
            // 拿到这个Node,移除它
            ListNode listNode = map.get(key);
            // 把这个listNode从链表上删除
            ListNode prev_node = listNode.prev;
            ListNode next_node = listNode.next;
            prev_node.next = next_node;
            next_node.prev = prev_node;
            // 把这个listNode弄到后面去
            ListNode insertPre = dummyTail.prev;
            insertPre.next = listNode;
            listNode.prev = insertPre;
            listNode.next = dummyTail;
            dummyTail.prev = listNode;
            map.put(key, listNode);
            return result;
        }
    }
}

/**
 * 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);
 */

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Imperva 数据库与安全解决方案

Imperva是网络安全解决方案的专业提供商&#xff0c;能够在云端和本地对业务关键数据和应用程序提供保护。公司成立于 2002 年&#xff0c;拥有稳定的发展和成功历史并于 2014 年实现产值1.64亿美元&#xff0c;公司的3700多位客户及300个合作伙伴分布于全球各地的90多个国家。…

工业网络监控中的IP保护与软件授权革新

未来的智能工厂离不开稳定而高效的通信网络&#xff0c;这些网络在支撑生产流程的同时&#xff0c;也面临着复杂的管理与安全挑战。PROCENTEC推出了一系列硬件和软件产品&#xff0c;如Atlas、Mercury和Osiris&#xff0c;以提供全面的网络监控和故障排除能力。然而&#xff0c…

基于springboot+vue实现的网上预约挂号管理系统 (源码+L文+ppt)4-104

结合现有六和医院网上预约挂号管理系统的特点&#xff0c;应用新技术&#xff0c;构建了六和医院网上预约挂号管理系统。首先从需求出发&#xff0c;对目前传统的六和医院网上预约挂号管理进行了详细的了解和分析。根据需求分析结果&#xff0c;对系统进行了设计&#xff0c;并…

QT for android 问题总结(QT 5.15.2)

1.配置好的sdk&#xff0c;显示设置失败 Android SDK Command-line Tools run. Android Platform-Tools installed. Command-line Tools (latest) 版本过高导致报错 &#xff0c;下载一个低版本的latest &#xff0c;替换掉之前latest中的文件。即可&#xff0c;latest 路径如…

NAS端最强音乐库,多平台服务支持。海康存储部署『Navidrome』

NAS端最强音乐库&#xff0c;多平台服务支持。海康存储部署『Navidrome』 哈喽小伙伴们好&#xff0c;我是Stark-C~ 对于我们NAS用户&#xff0c;我们总是喜欢将自己喜欢的音乐资源通过下载的方式保存在本地&#xff0c;不过海康存储目前对因音乐的支持和管理实在过于薄弱&am…

【论文阅读笔记】Wavelet Convolutions for Large Receptive Fields

1.论文介绍 Wavelet Convolutions for Large Receptive Fields 大感受野的小波卷积 2024 EECV Paper Code 2.摘要 近年来&#xff0c;人们试图通过增加卷积神经网络&#xff08;ConvolutionalNeuralNets&#xff0c;CNNs&#xff09;的核尺寸来模拟视觉变换器&#xff08;V…

2024年最新10款顶级项目管理软件排行

项目管理软件在现代项目管理中扮演着至关重要的角色&#xff0c;它不仅仅是一个工具&#xff0c;更是一种高效、系统化的方法来管理和优化项目流程&#xff0c;帮助项目经理和团队成员快速了解项目状态&#xff0c;加速项目进展。 进度猫 进度猫是一款以甘特图为向导的轻量级…

SAP ABAP开发学习——RFC

目录 RFC接口 定义 调用过程 RFC的通信 RFC通信情况 RFC接口系统 RFC的通信模式 RFC版本 RFC调用方式 Web Service接口 SAP创建Web Service示例 远程目标的维护 创建远程目标 外部系统访问设置 RFC的调用 RFC接口 定义 调用过程 RFC的通信 RFC通信情况 RFC接…

gps数据对接G7易流平台

之前伙伴对接G7物流平台获取温度、轨迹数据&#xff0c;写的一塌糊涂&#xff0c;今天来重新对接下。 G7易流 G7物联和易流科技合并后正式发布的品牌&#xff0c;主要面向生产制造与消费物流行业的货主及货运经营者提供软硬一体、全链贯通的SaaS服务。这包括订阅服务&#xff…

【网络】传输层协议TCP(下)

目录 四次挥手状态变化 流量控制 PSH标记位 URG标记位 滑动窗口 快重传 拥塞控制 延迟应答 mtu TCP异常情况 四次挥手状态变化 之前我们讲了四次挥手的具体过程以及为什么要进行四次挥手&#xff0c;下面是四次挥手的状态变化 那么我们下面可以来验证一下CLOSE_WAIT这…

高效新闻管理:SpringBoot框架应用

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理新闻稿件管理系统的相关信息成为必然。开发…

【已解决】C# NPOI如何设置单元格格式

前言 设置单元格格式我们做表格必须要的一步&#xff0c;那么如何对单元格进行设置呢&#xff1f;直接上图看看效果图先&#xff0c;我做的是一个居中然后字体变化的操作&#xff0c;其他的查他的手册即可。 解决方法 直接上代码 IWorkbook excelDoc new XSSFWorkbook();…

通过微调 Embedding 优化 RAG

大型语言模型 (LLM) 向用户和组织展示了巨大的潜力&#xff1b;它们的强大功能和生成能力使它们最近广受欢迎并被广泛接受。LLM 面临的一些缺点是无法以上下文感知的方式生成或响应用户给出的提示&#xff0c;听起来非常通用和开放&#xff0c;或者有时响应的信息已经过时。如果…

微信小程序生成二维码

目前是在开发小程序端 --> 微信小程序。然后接到需求&#xff1a;根据 form 表单填写内容生成二维码&#xff08;第一版&#xff1a;表单目前需要客户进行自己输入&#xff0c;然后点击生成按钮实时生成二维码&#xff0c;不需要向后端请求&#xff0c;不存如数据库&#xf…

用接地气的例子趣谈 WWDC 24 全新的 Swift Testing 入门(二)

概述 从 WWDC 24 开始&#xff0c;苹果推出了全新的测试机制&#xff1a;Swift Testing。利用它我们可以大幅度简化之前“老态龙钟”的 XCTest 编码范式&#xff0c;并且使得单元测试更加灵动自由&#xff0c;更符合 Swift 语言的优雅品味。 在这里我们会和大家一起初涉并领略…

Python的自然语言生成与对话系统介绍

1. 背景介绍 自然语言生成(Natural Language Generation&#xff0c;NLG)和对话系统是人工智能领域的重要研究方向。NLG 涉及将计算机理解的信息转换为自然语言文本&#xff0c;而对话系统则涉及计算机与用户之间的自然语言交互。Python 作为一种易于学习、易于使用的编程语言…

HarmonyOS NEXT 应用开发实战(十、从零设计一款个人中心页面详细示例)

随着HarmonyOS的不断发展&#xff0c;越来越多的开发者开始关注这个平台上的应用开发。本篇文章将详细讲解如何从零开始设计一款个人中心页&#xff0c;并在代码中实现其相关功能。 1. 项目结构设计 首先&#xff0c;我们需要设计一个合理的项目结构。我们将个人中心页面分为几…

Node.js 入门指南:从零开始构建全栈应用

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;node.js篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来node.js篇专栏内容:node.js-入门指南&#xff1a;从零开始构建全栈应用 前言 大家好&#xff0c;我是青山。作…

我们来学mysql -- 连接(原理版)

我们来学mysql -- 连接 题记两张表驱动表 题记 回到初学者的视角&#xff0c;navicat或命令窗口&#xff0c;呈现一行行数据&#xff0c;类比为excel工作薄更是深入人心通过join将多表的记录关联起来&#xff0c;这似乎也没啥问题只是好像是那么回事&#xff0c;又…似乎有想说…

ssm校园二手交易管理系统+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码看文章最下面 需要定制看文章最下面 目 录 1 绪论 1 1.1 选题背景 1 1.2 选题意义 1 1.3 研究内容 2 2 系统开发技术 3 2.1 MySQL数…