LeetCode 146. LRU 缓存

原题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

感谢博主题解点拨思路:LeetCode 0146. LRU 缓存:双向链表 + 哈希-CSDN博客

题目描述

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 O(1) 的平均时间复杂度运行。

样例1:

输入

["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]

输出

[null, null, null, 1, null, -1, null, -1, 3, 4]

解释

LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4

Tag

双向链表 哈希表

题目分析

LRU算法需要维护最久未使用的关键字,题目要求put和get都是O(1)复杂度,所使用的数据结构需要O(1)查询到关键字所在位置,并将位置调整到最近使用,同时给出关键字需要O(1)时间内得到value值。

思路

get中查询value做到O(1)比较容易,可以使用哈希表实现(此题使用map)。

put中在O(1)时间内使新加入元素调整到最近使用很多数据结构都能做到,诸如链表插头(尾)、队列入队、入栈等,调整节点位置包括找到节点位置+移动节点,O(1)调整位置直接用这些数据结构则不行。因此我们采用map<int,node*>的方式存储,根据关键字直接查到链表节点的地址,从而根据地址可以直接对节点进行操作。

设计链表头结点为最近使用,尾节点为最久未使用。节点位置在O(1)时间内找到后,需要将节点从原位置调整至队首,同时超过缓存容量还要删除节点(队尾元素)。使用单链表可以做到移动节点,但无法快速删除尾节点,而使用双向链表删除尾节点后,可以根据指向前一个节点的prev指针将前一个节点设为尾节点,下次溢出时可以快速删除。

C++代码

class node{
public:node *prev,*next;int key;int value;node(node *prev,node *next,int key,int value){this->key = key;this->value = value;this->prev = prev;this->next = next;}};class LRUCache {
private:int capacity;unordered_map<int,node*> mp;//node*:节点指针,存储链表中某个节点地址node *head,*tail;public:LRUCache(int capacity) {this->capacity = capacity;head = new node(nullptr,nullptr,0,0);tail = new node(head,nullptr,0,0);head->next = tail;}void adjust(node* temp) //将node移动到队首{temp->next = head->next;temp->prev = head;head->next = temp;temp->next->prev = temp;}int get(int key) {if(mp.count(key)){node* move = mp[key];/*删除节点*/move->prev->next = move->next;move->next->prev = move->prev;adjust(move);return mp[key]->value;}return -1;}void put(int key, int value) {if(mp.count(key)){node* temp = mp[key];mp[key]->value = value;//改值//删节点temp->prev->next = temp->next;temp->next->prev = temp->prev;adjust(temp);//调位置}else{node* newnode = new node(head,head->next,key,value);head->next->prev = newnode;head->next = newnode;mp[key] = newnode;}if(mp.size()>capacity){node* del = tail->prev;tail->prev = del->prev;del->prev->next = tail;mp.erase(del->key);}}
};/*** 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);*/

Debug

以下是我自己本地debug时用的代码


int main()
{freopen("stdin.txt","r",stdin);string op;LRUCache* obj = nullptr;while(cin>>op){if(op=="cache"){int capacity;cin>>capacity;obj = new LRUCache(capacity);cout<<"null ";}else if(op == "get"){int key;cin>>key;cout<<obj->get(key)<<" ";}else{int key,value;cin>>key>>value;obj->put(key,value);cout<<"null ";}}
}
cache
2
put
1 1
put
2 2
get
1 
put
3 3
get
2
put
4 4
get
1
get
3
get
4

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

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

相关文章

基于SpringBoot的课程答疑系统

目录 前言 一、技术栈 二、系统功能介绍 学生信息管理 科目类型管理 老师回答管理 我的收藏管理 学生问题 留言反馈 交流区 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#x…

vSAN7.0更换硬盘步骤

更换容量盘 预先检查 查看故障硬盘 清单->集群->监控->vsan->skyline运行->物理磁盘->运维运行状况 检查数据同步状态 清单->集群->监控->vsan->重新同步对象&#xff0c;数值全为0表示未重建。 数据迁移检查 清单->集群->监控->…

Java实现word excel ppt模板渲染与导出及预览 LibreOffice jodconverter

Java Office 一、文档格式转换 文档格式转换是office操作中经常需要进行一个操作&#xff0c;例如将docx文档转换成pdf格式。 java在这方面有许多的操作方式&#xff0c;大致可以分为内部调用&#xff08;无需要安装额外软件&#xff09;&#xff0c;外部调用&#xff08;需…

数据结构--Trie字符串统计

1、“Trie树” 作用&#xff1a; 高效地存储和查找字符串集合的数据结构。 2、“Trie树” 存储字符串的形式如下&#xff1a; 用 “0” 来表示 “根节点&#xff08;root&#xff09;”。存入一个字符串时&#xff0c;会在字符串最后结尾的那个字符节点打上标记。比如&#x…

Python中计算并使用if判断BMI指数

1 问题 如何对BMI进行计算并且使用if判断BMI指数的范围。 2 方法 对身高和体重这两个变量进行赋值&#xff08;体重单位&#xff1a;千克&#xff1b;身高单位&#xff1a;米。&#xff09;。对BMI进行计算&#xff0c;体重除以身高的平方。通过if条件语句进行判断&#xff0c;…

力扣第2390题 从字符串中移除星号 c++ stack容器?超内存 用双指针 巧解

题目 力扣第2390. 从字符串中移除星号 中等 给你一个包含若干星号 * 的字符串 s 。 在一步操作中&#xff0c;你可以&#xff1a; 选中 s 中的一个星号。移除星号 左侧 最近的那个 非星号 字符&#xff0c;并移除该星号自身。 返回移除 所有 星号之后的字符串。 注意&am…

babel.config.js配置文件详解

文章目录 一、前言三、babel 详解四、拓展阅读 一、前言 项目开发阶段&#xff0c;使用可选链操作符 ?. 出现以下编译报错问题&#xff1a; 分析&#xff1a;由于可选链操作符 ?. 是ES2020&#xff08;即ES11&#xff09;中推出的新语法&#xff0c;允许我们不需要校验当前属…

FreeRTOS(以STM32F1系列为例子)

目录 任务管理任务函数任务控制块顶层任务状态创建任务xTaskCreatexTaskCreateStaticxTaskCreateRestricted 任务优先级和心跳设置心跳设置优先级概述vTaskPrioritySetuxTaskPriorityGet 非运行态扩充阻塞态vTaskDelay挂起状态vTaskSuspend就绪状态完整的状态转换图延迟函数vTa…

Spring Boot的自动装配中的@ConditionalOnBean条件装配注解在Spring启动过程中,是如何保证处理顺序靠后的

前言 为什么Spring Boot条件注解那么多&#xff0c;而标题中是ConditionalOnBean呢&#xff1f; 因为&#xff0c;相比之下我们用的比较多的条件装配注解也就是ConditionalOnClass、ConditionalOnBean了&#xff0c;而ConditionalOnClass对顺序并不敏感&#xff08;说白了就是判…

stream对list数据进行多字段去重

方法一&#xff1a; //根据sj和name去重 List<NursingHandover> testList list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getj() ";" o.getName() ";&…

《数据结构、算法与应用C++语言描述》-栈的应用-开关盒布线问题

开关盒布线问题 问题描述 在开关盒布线问题中&#xff0c;给定一个矩形布线区域&#xff0c;其外围有若干管脚。两个管脚之间通过布设一条金属线路来连接。这条金属线路称为电线&#xff0c;它被限制在矩形区域内。两条电线交叉会发生电流短路。因此&#xff0c;电线不许交叉…

根据GWAS数据估算样本量N和使用千人基因组填充maf的参考文献

https://github.com/GenomicSEM/GenomicSEM/wiki/2.1-Calculating-Sum-of-Effective-Sample-Size-and-Preparing-GWAS-Summary-Statistics

SpringBoot全局异常处理请求参数校验及响应体包装

一、响应体包装 全局接口响应体包装&#xff0c;返回json数据支持对部分接口或者类放行 # mvc配置mvc:body-exclude-paths:- /test/**body-exclude-classes:- com.qiangesoft.rdp.starter.XXXimport lombok.Data; import org.springframework.boot.context.properties.Configu…

AI绘画本地部署Stable Diffusion web UI

AI绘画本地部署Stable Diffusion web UI 一 、项目介绍 A browser interface based on Gradio library for Stable Diffusion. 项目地址&#xff1a;GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UI 这是一个可以通过直接输入描述性文字文本来生成…

Verilog参数定义与仿真模块中的参数修改

文章目录 参数方式定义参数的优势rtl模块中的参数定义模块名后定义参数parameter定义参数 仿真模块中的参数修改例化时修改defparam修改 总结与说明附录&#xff1a;测试代码 参数方式定义参数的优势 当一个模块被另一个模块引用例化时&#xff0c;高层模块可以对低层模块的参…

MD5 绕过第三式:ffifdyop

文章目录 参考环境推荐阅读雾现两个 PHP 文件表结构分析 雾散ASCII 编码二进制数据到 ASCII 文本的转化绕过原理ffifdyop绕过 ffifdyop 的批量化生产批量化生产注意事项细节一字之差运算符优先级 实际需要遵守的规则 生产机器 参考 项目描述搜索引擎Bing、GoogleAI 大模型文心…

幂级数和幂级数的和函数有什么关系?

幂级数和幂级数的和函数有什么关系&#xff1f; 本文例子引用自&#xff1a;80_1幂级数运算&#xff0c;逐项积分、求导【小元老师】高等数学&#xff0c;考研数学 求幂级数 ∑ n 1 ∞ 1 n x n \sum\limits_{n1}^{\infty}\frac{1}{n}x^n n1∑∞​n1​xn 的和函数 &#xff…

分析各种表达式求值过程

目录 算术运算与赋值 编译器常用的两种优化方案 常量传播 常量折叠 加法 Debug编译选项组下编译后的汇编代码分析 Release开启02执行效率优先 减法 Release版下优化和加法一致&#xff0c;不再赘述 乘法 除法 算术结果溢出 自增和自减 关系运算与逻辑运算 JCC指…

乐鑫 ESP-Mesh-Lite在windows下的开发环境搭建

ESP-Mesh-Lite的开发环境由于没有官方教程&#xff0c;折腾了好几天。环境搭建主要还是参考ESP-MDF环境搭建&#xff0c;特别注意的是必须要在CMD环境下操作&#xff0c;不能用POWER SHELL。 ESP-Mesh-Lite目前支持到5.1的SDK&#xff0c;当然4.4也是可以用的。首先上Gitee或G…

Android 查看路由表

Android 查看路由表_android 路由表_念雅的博客-CSDN博客