【LeetCode-中等题】146. LRU 缓存
文章目录
- 题目
- 方法一:直接继承LinkedHashMap调用api
- 方法二:自定义LinkedHashMap = HashMap + ListNode == LinkedHashMap
题目
LRU缓存是什么:LRU缓存机制,你想知道的这里都有
实现 LRU 缓存算法

方法一:直接继承LinkedHashMap调用api
class LRUCache extends LinkedHashMap<Integer, Integer>{private int capacity;public LRUCache(int capacity) {super(capacity, 0.75F, true);this.capacity = capacity;}public int get(int key) {return super.getOrDefault(key, -1);}public void put(int key, int value) {super.put(key, value);}@Overrideprotected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {return size() > capacity; }
}
方法二:自定义LinkedHashMap = HashMap + ListNode == LinkedHashMap
map —>key存 integer value存链表节点
ListNode 存 next 和prev 引用 以及 存 key 和value 具体值

图解:官方图解
步骤:
- 定义一个自定义的双向链表节点类 DLinkedNode,该类包含 key 和 value 字段,并且具有 prev 和 next 指针用于构建双向链表。
- 创建一个哈希表 cache 用于存储键值对,其中键为索引,值为双向链表的节点。
- 定义变量 size 表示当前哈希表中已存储的键值对数量。
- 定义变量 capacity 表示哈希表的容量。
- 创建伪头部节点 head 和伪尾部节点 tail,并将它们连接起来形成一个空的双向链表。
方法列表:
- 构造函数 LRUCache(int capacity):初始化缓存的容量,同时初始化 size、capacity、head 和 tail 变量。
- int get(int key):获取指定键对应的值,如果键不存在则返回 -1。如果键存在,则通过哈希表定位到双向链表中的节点,并将该节点移到链表头部,然后返回节点的值。
- void put(int key, int value):插入或更新键值对。如果键已存在,则更新对应的值,并将对应的节点移到链表头部。如果键不存在,则创建一个新的节点,添加到哈希表和链表头部。如果插入后超出容量,则删除尾部节点,并从哈希表中移除对应的记录。
- DLinkedNode removeTail():在超出容量时删除尾部节点,并返回删除的尾部节点。
- void addToHead(DLinkedNode newNode):将指定节点添加到伪头部节点的后面。
- void moveToHead(DLinkedNode node):将指定节点移到伪头部节点的后面,即删除原位置的节点并将其添加到伪头部节点后面。
- void removeNode(DLinkedNode node):从双向链表中删除指定节点。
class LRUCache {/*** 自定义双向链表*/class DLinkedNode {int key;int value;DLinkedNode prev;DLinkedNode next;public DLinkedNode() {}public DLinkedNode(int _key, int _value) {key = _key; value = _value;}}private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();//定义哈希表 key为索引 value为双向链表的节点private int size;//map的存值后的大小private int capacity;//map 的容量private DLinkedNode head, tail; //定义双向链表的伪头部和伪尾部节点/*** 定义初始容量方法* @param capacity*/public LRUCache(int capacity) { //定义初始容量方法this.size = 0;this.capacity = capacity;// 使用伪头部和伪尾部节点head = new DLinkedNode();tail = new DLinkedNode();head.next = tail;tail.prev = head;}/*** 依据key获取对应value* @param key* @return*/public int get(int key) {DLinkedNode node = cache.get(key);//获取key对应的链表节点if (node == null) { //如果node为null 说明key没有对应的value值return -1;}// 如果 key 存在,先通过哈希表定位,再移到头部moveToHead(node);//将待get的节点移动到头部,再返回节点的值return node.value;}/*** 往哈希表中添加元素的方法* @param key* @param value*/public void put(int key, int value) {DLinkedNode node = cache.get(key);//put时 先获取这个key的位置有没有值 有?覆盖原值 没有就插入进去if (node == null) {// 如果 key 不存在,创建一个新的节点DLinkedNode newNode = new DLinkedNode(key, value);// 添加进哈希表cache.put(key, newNode);// 添加至双向链表的头部addToHead(newNode);size++; //map集合元素+1if (size > capacity) {// 如果超出容量,删除双向链表的尾部节点DLinkedNode tail = removeTail(); //从链表中把尾结点删除,并且方法得返回这个节点 方便map把这个节点对应的元素remove掉cache.remove(tail.key);size--;}}else{// 如果 key 存在,覆盖原值,并移到链表头部node.value = value;moveToHead(node);}}/*** 超出容量时删除尾部节点 并且返回尾部节点 方便对清除map中的残留* @return*/private DLinkedNode removeTail() {DLinkedNode tailNode = tail.prev;//获取伪尾节点的前一个节点 即链表真实的尾节点removeNode(tailNode);return tailNode;//返回尾部节点 方便对清除map中的残留}/*** 新增节点时节点添加到伪头结点后面的位置* @param newNode*/private void addToHead(DLinkedNode newNode) {newNode.prev = head;newNode.next = head.next;head.next.prev = newNode;head.next = newNode;}/*** get方法获取key对应value* put方法出现重复key时 覆盖原value* 这两种情况都会触发将操作的节点移动到伪首节点的后面* @param node*/private void moveToHead(DLinkedNode node) {//删除原位置的自己removeNode(node);//将自己添加到伪首节点的后面addToHead(node);//调用上面写过的将节点添加到伪首节点的后面}/*** 删除node节点* @param node*/private void removeNode(DLinkedNode node) {node.prev.next = node.next;node.next.prev = node.prev;node.next = null;node.prev = null;}}
相关文章:
【LeetCode-中等题】146. LRU 缓存
文章目录 题目方法一:直接继承LinkedHashMap调用api方法二:自定义LinkedHashMap HashMap ListNode LinkedHashMap 题目 LRU缓存是什么:LRU缓存机制,你想知道的这里都有 实现 LRU 缓存算法 方法一:直接继承Linked…...
表白墙程序
目录 一、页面代码部分 二、设计程序 二、实现 doPost编辑 三、实现 doGet 四、前端代码部分 五、使用数据库存储数据 一、页面代码部分 在之前的一篇博客中,已经写过了表白墙的页面代码实现,这里就不再重复了 页面代码如下: <!…...
git 本地仓库关联到远程仓库
将本地仓库关联到远程仓库 方式一:远程仓库没有文件 第一步: git init(初始化git仓库) 第二步: git remote add 地址(设置remote地址) 第三步: git add . (将所有变…...
Introducing Language Guidance in Prompt-based Continual Learning
本文是LLM系列文章,针对《Introducing Language Guidance in Prompt-based Continual Learning》的翻译。 基于提示的持续学习中引入语言指导 摘要1 引言2 相关工作3 背景4 基于提示的持续学习语言指导5 实验6 结论 摘要 持续学习旨在学习一系列任务的单一模型&am…...
Matlab(数值微积分)
目录 1.多项式微分与积分 1.1 微分 1.2 多项式微分 1.3 如何正确的使用Matlab? 1.3.1 Matlab表达多项式 1.3.2 polyval() 多项式求值 1.3.3 polyder()多项式微分 1.4 多项式积分 1.4.1 如何正确表达 1.4.2 polyint() 多项式积分 2.数值的微分与积分 2.1 数值微分 2…...
【数据结构回顾】
数据结构回顾 一、单链表二、单循环链表 一、单链表 #include <stdio.h> #include <stdlib.h>typedef struct Node {int data;Node *next; }Node;Node* initList() {Node *list (Node*)malloc(sizeof(Node));list->data 0;list->next NULL;return list; }…...
QT创建可移动点类
效果如图所示: 创建新类MovablePoint,继承自QWidget. MovablePoint头文件: #ifndef MOVABLEPOINT_H #define MOVABLEPOINT_H#include <QWidget> #include <QPainter> #include <QPaintEvent> #include <QStyleOption> #includ…...
Flutter启动页
效果图 import dart:async; import package:flutter/cupertino.dart; import package:flutter/material.dart; import jumpPage.dart;class TransitPage extends StatefulWidget {const TransitPage({super.key});overrideState<TransitPage> createState() > _Trans…...
读word模板批量生成制式文件
文章目录 1、Maven依赖2、.docx或.doc格式的word模板准备3、读word模板,批量替换代码域,生成文件,demo4、结果展示 1、Maven依赖 <dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagre…...
Node.js crypto模块 加密算法
背景 微信小程序调用飞蛾热敏纸打印机,需要进行参数sig签名校验,使用的是sha1进行加密 // 通过crypto.createHash()函数,创建一个hash实例,但是需要调用md5,sha1,sha256,sha512算法来实现实例的…...
Win11 避坑安装WSL2 Ubuntu22.04
开始之前以管理员身份打开 PowerShell 启用适用于 Linux 的 Windows 子系统 需要先启用“适用于 Linux 的 Windows 子系统”可选功能,然后才能在 Windows 上安装 Linux 分发。 PowerShell然后输入以下命令: dism.exe /online /enable-feature /featur…...
ESP8266+继电器+MQTT+VUE 实现远程开关灯
超详细教程 – ESP8266继电器MQTTVUE 实现远程开关灯 超详细教程 – ESP8266继电器MQTTVUE 实现远程开关灯 接线图 NC(通常闭合)与COM(公共)、NO(通常开放)与COM 是继电器引脚的不同配置,用于不…...
Android中级——四大组件工作过程
四大组件工作过程 ActivityServicestartService()过程bindService()过程 BroadcastReceiver注册过程发送和接收过程 ContentProvider Activity startActivity()最终都会调用到startActivityForResult() public void startActivityForResult(RequiresPermission Intent intent…...
【RabbitMQ】RabbitMQ 服务无法启动。系统出错。发生系统错误 1067。进程意外终止。
问题描述 RabbitMQ 服务无法启动。 rabbitmq-service.bat startRabbitMQ 服务正在启动 . RabbitMQ 服务无法启动。系统出错。发生系统错误 1067。进程意外终止。原因分析 RabbitMQ和Erlang版本不匹配。 解决方案 查询并安装RabbitMQ版本对应Erlang版本 https://www.rabbitm…...
如何理解attention中的Q、K、V?
y直接用torch实现一个SelfAttention来说一说: 1、首先定义三哥线性变换,query,key以及value: class BertSelfAttention(nn.Module):self.query nn.Linear(config.hidden_size, self.all_head_size)#输入768,输出768…...
Redis----取代RabbitMq 和 Kafka的解决方案
背景 已知rabbitmq和kafka作为消息中间件来给程序之间增加异步消息传递功能,这两个中间件都是专业的,功能也很强,但是有的时候过于复杂,对于只有一组消费者的消息队列,使用Redis 就可以轻松搞定。 异步消息队列 读者…...
动态规划之连续乘积最大子数组 连续和最大子数组
一. 连续和最大子数组 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。 示例 1: 输入:nums [-2,1,-3,4,-1,2,1,-5,…...
keil在点击debug无法运行(全速运行)
1、今天发现我之前可以debug的程序,在板子上无法debug了,打断点完全没用 2、换了电脑,带板子过去也这样,之前可以运行的代码都debug不了 3、按照网上的方法,都不行,全速运行,单步执行都是灰色…...
go语言-协程
mOS结构体 每一种操作系统不同的线程信息 g给g0栈给g0协程内存中分配的地址,记录函数跳转信息, 单线程循环 0.x版本 1.0版本 多线程循环 操作系统并不知道Goroutine的存在 操作系统线程执行一个调度循环,顺序执行Goroutine 调度循环非常…...
如何伪造http头,让后端认为是本地访问
0x00 前言 这个知识点纯粹就是为了ctf准备的,很少有系统会出现这种情况。 0x01 正文 1.host头 如果后端从host取值来判断是否是本地就可以通过此方法进行绕过: host: 127.0.0.12.X-Forwarded-For X-Forwarded-For(XFF)是用来…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
