LRU 缓存

题目链接

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中的相应值进行更新

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

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

相关文章

李子转债上市价格预测

李子转债 基本信息 转债名称&#xff1a;李子转债&#xff0c;评级&#xff1a;AA&#xff0c;发行规模&#xff1a;6.0亿元。 正股名称&#xff1a;李子园&#xff0c;今日收盘价&#xff1a;18.06元&#xff0c;转股价格&#xff1a;19.47元。 当前转股价值 转债面值 / 转股…

RabbitMQ笔记--消息中间件,rabbitmq安装及简单使用

1.消息中间件 消息&#xff1a;指在应用间传送的数据。 消息队列中间件&#xff1a;指利用高效可靠的消息传递机制进行与平台无关的数据交流&#xff0c;并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型&#xff0c;可以在分布式环境下扩展进程间的通…

Elasticsearch【全文检索、倒排索引、应用场景、对比Solr、数据结构】(一)-全面详解(学习总结---从入门到深化)

目录 Elasticsearch介绍_全文检索 Elasticsearch介绍_倒排索引 Elasticsearch介绍_Elasticsearch的出现 Elasticsearch介绍_Elasticsearch应用场景 Elasticsearch介绍_Elasticsearch对比Solr Elasticsearch介绍_Elasticsearch数据结构 Elasticsearch介绍_全文检索 Elasti…

UILabel左上角对齐

设计有个需求&#xff0c;需要文字两行显示&#xff0c;一行的时候左上角对齐&#xff0c;比较常见的需求。 老的办法一般来说是根据宽计算好frame大小&#xff0c;然后重新设置frame。不过感觉这种方式比较麻烦&#xff0c;想了想能不能通过约束来完成这个事情呢。 本着这个思…

(论文翻译)PRUNING FILTER IN FILTER《滤波器中的剪枝滤波器》

公式不清楚的地方请对照英文原文进行查看&#xff1a;原文链接 ABSTRACT 剪枝已成为现代神经网络压缩和加速的一种非常有效的技术。现有的剪枝方法可分为两大类:滤波器剪枝(FP)和权重剪枝(WP)。与WP相比&#xff0c;FP在硬件兼容性方面胜出&#xff0c;但在压缩比方面失败。为了…

springboot开发PC端桌面应用

一、需求描述&#xff1a; 1、要求桌面能在window、Linux和macos系统上运行 2、用户自定义数据筛选策略&#xff0c;策略可通过excel导入导出 3、选择多个excel文件通过策略过滤生成新的excel 二、技术选型及集成环境配置&#xff1a; 1、PC端跨平台直接选用javafx来作为桌…

SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现

系列文章&#xff1a; SpringBoot Vue前后端分离项目实战 || 一&#xff1a;Vue前端设计 SpringBoot Vue前后端分离项目实战 || 二&#xff1a;Spring Boot后端与数据库连接 SpringBoot Vue前后端分离项目实战 || 三&#xff1a;Spring Boot后端与Vue前端连接 SpringBoot V…

从零开始制作一个Web蜜罐扫描器(5)

从零开始制作一个Web蜜罐扫描器(3)_luozhonghua2000的博客-CSDN博客 打开一个蜜罐: 查看源码: 这个./js/portraitjs非常引人注入,点进去看一下 很明显是被混淆过了,结合语义来理解,这是portrait=画像,那么可以大胆猜测这段ison是黑客画像用的.猜测了就要进行验证,这里在…

Kafka request.log中RequestQueueTimeMs、LocalTimeMs、RemoteTimeMs、ThrottleTimeMs、含义

Kafka request.log中RequestQueueTimeMs、LocalTimeMs、RemoteTimeMs、ThrottleTimeMs、含义 要理解各个延时项的含义&#xff0c;必须从Kafka收到TCP请求、处理请求到返回TCP包整个流程开始梳理 RequestQueueTimeMs Processor 执行processNewResponses() 方法&#xff0c;不…

软件工程师,学习下JavaScript ES6新特性吧

概述 作为一名软件工程师&#xff0c;不管你是不是前端开发的岗位&#xff0c;工作中或多或少都会用到一点JavaScript。JavaScript是大家所了解的语言名称&#xff0c;但是这个语言名称是Oracle公司注册的商标。JavaScript的正式名称是ECMAScript。1996年11月&#xff0c;JavaS…

RT-Thread 互补滤波器 (STM32 + 6 轴 IMU)

作者&#xff1a;wuhanstudio 原文链接&#xff1a;https://zhuanlan.zhihu.com/p/611568999 最近在看无人驾驶的 Prediction 部分&#xff0c;可以利用 EKF (Extended Kalman Filter) 融合不同传感器的数据&#xff0c;例如 IMU, Lidar 和 GNSS&#xff0c;从而给出更加准确的…

Go语言github.com/gorilla/websocket框架websocket协议通信实战

websocket是实际开发中比较常用的应用层协议&#xff0c;本文利用github.com/gorilla/websocket框架进行websocket通信实战。 目录 1.下载github.com/gorilla/websocket 2.websocket服务端 3.websocket Go客户端 4.websocket 网页客户端 5.运行结果展示 1.下载github.com…

Red Hat Subscription 开发者订阅与激活订阅

目录 前言 进入开发者页面 创建红帽账户 阅读Red Hat订阅&#xff1b; 激活订阅 查看订阅状态 前言 使用命令时会出现以提示&#xff0c;命令不可正常使用。 根据提示信息&#xff0c;我们可以知道&#xff0c;需要通过Red Hat Subscription&#xff0c;开发者订阅。 …

图像分类——图像增强方法

目录 常用的图像增强方法tf.image进行图像增强翻转和裁剪颜色变换 使用ImageDataGenerator(进行图像增强) 常用的图像增强方法 tf.image进行图像增强 离线实现 import tensorflow as tf import matplotlib.pyplot as plt import numpy as npcatplt.imread(./cat.jpg) plt.ims…

Scala中的集合

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 目录 一、集合简介 二、集合关系继承图 一、集合简介 Java中的集合&#xff1a; Scala中的集合&#xff1a; Scala的集合有三大类&#xff1a;序列Seq、集Set、映射Map&#xff0c;所有的集合…

单片机基于stm32单片机的数字温度计设计_kaic

摘 要 古往今来,陶瓷在我们的生活中一直都是不可或缺的物品,而随着当今社会经济的快速发展,人们对于这些高档陶瓷产品的使用性能和产品质量上的要求也愈加严格。那么在陶瓷品的生产过程中,想要提高陶瓷品的品质和合格率,能够随时监测温度的温度计是必不可少的。 本课题的研究是…

MySQL单表查询练习题

目录 第一题 第二题 第三题 第一题 1.创建数据表pet&#xff0c;并对表进行插入、更新与删除操作&#xff0c;pet表结构如表8.3所示。 (1&#xff09;首先创建数据表pet&#xff0c;使用不同的方法将表8.4中的记录插入到pet表中。 mysql> create table pet( name varchar(…

IDEA+SpringBoot+mybatis+SSM+layui+Mysql客户管理系统源码

IDEASpringBootmybatisSSMlayuiMysql客户管理系统 一、系统介绍1.环境配置 二、系统展示1. 管理员登录2.修改密码3.客户管理4.添加客户5.充值记录管理6.消费记录管理7.客户类型8.添加客户类型 三、部分代码UserMapper.javaLoginController.javaUser.java 四、其他获取源码 一、…

【MQ】Windows上RabbitMQ的安装与启动

文章目录 下载Erlang安装RabbitMQ 下载Erlang RabbitMQ基于Erlang语言&#xff0c;因此使用RabbitMQ之前需要先安装Erlang&#xff0c;如下 Erlang语言下载 这里我是用的是25.2.2这个版本&#xff0c;我的机器是64bit的&#xff0c;所以下win64的即可。 下载完毕安装包之后点…

List移除元素的四种方式

List 移除某个元素 四种方式&#xff1a; 方式一&#xff0c;使用 Iterator &#xff0c;顺序向下&#xff0c;如果找到元素&#xff0c;则使用 remove 方法进行移除。方式二&#xff0c;倒序遍历 List &#xff0c;如果找到元素&#xff0c;则使用 remove 方法进行移除。方式…