当前位置: 首页 > news >正文

【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 具体值
在这里插入图片描述

图解:官方图解

步骤:

  1. 定义一个自定义的双向链表节点类 DLinkedNode,该类包含 key 和 value 字段,并且具有 prev 和 next 指针用于构建双向链表。
  2. 创建一个哈希表 cache 用于存储键值对,其中键为索引,值为双向链表的节点。
  3. 定义变量 size 表示当前哈希表中已存储的键值对数量。
  4. 定义变量 capacity 表示哈希表的容量。
  5. 创建伪头部节点 head 和伪尾部节点 tail,并将它们连接起来形成一个空的双向链表。

方法列表:

  1. 构造函数 LRUCache(int capacity):初始化缓存的容量,同时初始化 size、capacity、head 和 tail 变量。
  2. int get(int key):获取指定键对应的值,如果键不存在则返回 -1。如果键存在,则通过哈希表定位到双向链表中的节点,并将该节点移到链表头部,然后返回节点的值。
  3. void put(int key, int value):插入或更新键值对。如果键已存在,则更新对应的值,并将对应的节点移到链表头部。如果键不存在,则创建一个新的节点,添加到哈希表和链表头部。如果插入后超出容量,则删除尾部节点,并从哈希表中移除对应的记录。
  4. DLinkedNode removeTail():在超出容量时删除尾部节点,并返回删除的尾部节点。
  5. void addToHead(DLinkedNode newNode):将指定节点添加到伪头部节点的后面。
  6. void moveToHead(DLinkedNode node):将指定节点移到伪头部节点的后面,即删除原位置的节点并将其添加到伪头部节点后面。
  7. 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 缓存

文章目录 题目方法一&#xff1a;直接继承LinkedHashMap调用api方法二&#xff1a;自定义LinkedHashMap HashMap ListNode LinkedHashMap 题目 LRU缓存是什么&#xff1a;LRU缓存机制&#xff0c;你想知道的这里都有 实现 LRU 缓存算法 方法一&#xff1a;直接继承Linked…...

表白墙程序

目录 一、页面代码部分 二、设计程序 二、实现 doPost​编辑 三、实现 doGet 四、前端代码部分 五、使用数据库存储数据 一、页面代码部分 在之前的一篇博客中&#xff0c;已经写过了表白墙的页面代码实现&#xff0c;这里就不再重复了 页面代码如下&#xff1a; <!…...

git 本地仓库关联到远程仓库

将本地仓库关联到远程仓库 方式一&#xff1a;远程仓库没有文件 第一步&#xff1a; git init&#xff08;初始化git仓库&#xff09; 第二步&#xff1a; git remote add 地址&#xff08;设置remote地址&#xff09; 第三步&#xff1a; git add . &#xff08;将所有变…...

Introducing Language Guidance in Prompt-based Continual Learning

本文是LLM系列文章&#xff0c;针对《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创建可移动点类

效果如图所示&#xff1a; 创建新类MovablePoint&#xff0c;继承自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模板&#xff0c;批量替换代码域&#xff0c;生成文件&#xff0c;demo4、结果展示 1、Maven依赖 <dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagre…...

Node.js crypto模块 加密算法

背景 微信小程序调用飞蛾热敏纸打印机&#xff0c;需要进行参数sig签名校验&#xff0c;使用的是sha1进行加密 // 通过crypto.createHash()函数&#xff0c;创建一个hash实例&#xff0c;但是需要调用md5&#xff0c;sha1&#xff0c;sha256&#xff0c;sha512算法来实现实例的…...

Win11 避坑安装WSL2 Ubuntu22.04

开始之前以管理员身份打开 PowerShell 启用适用于 Linux 的 Windows 子系统 需要先启用“适用于 Linux 的 Windows 子系统”可选功能&#xff0c;然后才能在 Windows 上安装 Linux 分发。 PowerShell然后输入以下命令&#xff1a; dism.exe /online /enable-feature /featur…...

ESP8266+继电器+MQTT+VUE 实现远程开关灯

超详细教程 – ESP8266继电器MQTTVUE 实现远程开关灯 超详细教程 – ESP8266继电器MQTTVUE 实现远程开关灯 接线图 NC&#xff08;通常闭合&#xff09;与COM&#xff08;公共&#xff09;、NO&#xff08;通常开放&#xff09;与COM 是继电器引脚的不同配置&#xff0c;用于不…...

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来说一说&#xff1a; 1、首先定义三哥线性变换&#xff0c;query&#xff0c;key以及value&#xff1a; class BertSelfAttention(nn.Module):self.query nn.Linear(config.hidden_size, self.all_head_size)#输入768&#xff0c;输出768…...

Redis----取代RabbitMq 和 Kafka的解决方案

背景 已知rabbitmq和kafka作为消息中间件来给程序之间增加异步消息传递功能&#xff0c;这两个中间件都是专业的&#xff0c;功能也很强&#xff0c;但是有的时候过于复杂&#xff0c;对于只有一组消费者的消息队列&#xff0c;使用Redis 就可以轻松搞定。 异步消息队列 读者…...

动态规划之连续乘积最大子数组 连续和最大子数组

一. 连续和最大子数组 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,…...

keil在点击debug无法运行(全速运行)

1、今天发现我之前可以debug的程序&#xff0c;在板子上无法debug了&#xff0c;打断点完全没用 2、换了电脑&#xff0c;带板子过去也这样&#xff0c;之前可以运行的代码都debug不了 3、按照网上的方法&#xff0c;都不行&#xff0c;全速运行&#xff0c;单步执行都是灰色…...

go语言-协程

mOS结构体 每一种操作系统不同的线程信息 g给g0栈给g0协程内存中分配的地址&#xff0c;记录函数跳转信息&#xff0c; 单线程循环 0.x版本 1.0版本 多线程循环 操作系统并不知道Goroutine的存在 操作系统线程执行一个调度循环&#xff0c;顺序执行Goroutine 调度循环非常…...

如何伪造http头,让后端认为是本地访问

0x00 前言 这个知识点纯粹就是为了ctf准备的&#xff0c;很少有系统会出现这种情况。 0x01 正文 1.host头 如果后端从host取值来判断是否是本地就可以通过此方法进行绕过&#xff1a; host: 127.0.0.12.X-Forwarded-For X-Forwarded-For&#xff08;XFF&#xff09;是用来…...

如何快速配置FanControl风扇控制:从安装到优化的完整指南

如何快速配置FanControl风扇控制&#xff1a;从安装到优化的完整指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending…...

av1编码--比特流结构

目录 2.2.1 序列头信息 2.2.2 帧头信息 2.2.4 时间分隔符信息 2.2.5 切片组信息 AV1 比特流是由一系列名为开放比特流单元&#xff08;OBU&#xff09;的数据单元组成。每个 OBU 由一个可变长度的字节串&#xff08;Byte String&#xff09;组成。具体来讲&#xff0c;OBU 包…...

微信红包背后的技术博弈:一个Android辅助服务的实战剖析

微信红包背后的技术博弈&#xff1a;一个Android辅助服务的实战剖析 【免费下载链接】WeChatLuckyMoney :money_with_wings: WeChats lucky money helper (微信抢红包插件) by Zhongyi Tong. An Android app that helps you snatch red packets in WeChat groups. 项目地址:…...

yolo 源码与模型

YOLOv8 官方源码、预训练模型&#xff08;.pt&#xff09;、导出 ONNX 模型、以及 ROS2 C 部署源码&#xff08;含检测框输出&#xff09;&#xff0c;全部是可直接用的工业级版本。 一、YOLOv8 官方源码&#xff08;Ultralytics&#xff09; 1. GitHub 源码地址&#xff08;最…...

ARMv8/v9虚拟化核心:SCTLR_EL2寄存器详解与配置实践

1. AArch64 SCTLR_EL2系统寄存器深度解析在ARMv8/v9架构的异常级别&#xff08;Exception Level&#xff09;设计中&#xff0c;EL2作为虚拟化管理的核心层级&#xff0c;其系统控制寄存器SCTLR_EL2承载着关键的系统配置功能。这个64位寄存器不仅控制着EL2自身的内存管理和系统…...

math 7 [parallel lines] 2026.05.22

math 7 [parallel lines] 2026.05.22 平行线练习...

内网规划练习

本文基于172.16.0.0/16 内网规划&#xff0c;实现双核心交换机互为备份&#xff0c;整合 VLAN、MSTP、VRRP、Eth-Trunk、DHCP 中继、NAT outbound 等技术&#xff0c;满足 PC 自动获取 IP、内网互通、访问公网及 ISP 环回的全业务需求。一、网络需求与规划内网地址&#xff1a;…...

免费一键去图片水印的app有哪些?2026年免费去水印app推荐与测评

在社交媒体时代&#xff0c;我们经常会遇到需要去除图片水印的情况——无论是处理自己的作品&#xff0c;还是优化电商产品图&#xff0c;亦或是整理素材库。但去水印听起来复杂&#xff0c;实际上现在已经有很多免费工具可以一键搞定。本文为你盘点2026年最实用的去水印解决方…...

真正的爱是接受对方本来的样子

武志红说&#xff1a;爱是如TA所是&#xff0c;而非如你所愿。真正的爱是接受对方本来的样子&#xff0c;而不是把对方改造成你想要的样子。爱是如TA所是意味着&#xff1a;你爱的是这个人本身&#xff0c;而不是你想象中的TA。你不需要改变对方来满足你的期望。你接受TA的优点…...

茉莉花插件:Zotero中文文献管理的终极解决方案,5分钟打造高效科研工作流

茉莉花插件&#xff1a;Zotero中文文献管理的终极解决方案&#xff0c;5分钟打造高效科研工作流 【免费下载链接】jasminum A Zotero add-on to retrive CNKI meta data. 一个简单的Zotero 插件&#xff0c;用于识别中文元数据 项目地址: https://gitcode.com/gh_mirrors/ja/…...