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

【leetcode100-035】【链表/哈希链表】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) 的平均时间复杂度运行。

【思路】

  • 首先从数据结构的角度来想,想要方便地改变元素排序,选择链表比较合适,且可能频繁涉及到节点的移除,考虑使用双链表,最后还想要在常数时间取放,我们选择用哈希表来建立key和链表节点的映射。C++中没有像py和java那样提供现成的链表+哈希表结构,本题显然是希望我们来手撕一个。
  • 从数据的操作来看,我们可以把常见的可复用的动作先提取出来封装成函数,具体来说有五种情形:get且存在、get但不存在、put且存在、put且不存在且不超额、put且存在且超额;其中涉及到的操作有:将刚刚被使用的元素提到当前最不可能被删除位置(约定头部)(move),在头部加新节点(add),在尾部删节点(remove)。
  • 然后就只剩一些分支条件判断,链表指针的操作了,不做赘述。

【题解】

struct DLinkedNode {int key, value;DLinkedNode* prev;DLinkedNode* next;DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {}DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}
};class LRUCache {
private:unordered_map<int, DLinkedNode*> cache;DLinkedNode* head;DLinkedNode* tail;int size;int capacity;public:LRUCache(int _capacity): capacity(_capacity), size(0) {// 使用伪头部和伪尾部节点head = new DLinkedNode();tail = new DLinkedNode();head->next = tail;tail->prev = head;}int get(int key) {if (!cache.count(key)) {return -1;}// 如果 key 存在,先通过哈希表定位,再移到头部DLinkedNode* node = cache[key];moveToHead(node);return node->value;}void put(int key, int value) {if (!cache.count(key)) {// 如果 key 不存在,创建一个新的节点DLinkedNode* node = new DLinkedNode(key, value);// 添加进哈希表cache[key] = node;// 添加至双向链表的头部addToHead(node);++size;if (size > capacity) {// 如果超出容量,删除双向链表的尾部节点DLinkedNode* removed = removeTail();// 删除哈希表中对应的项cache.erase(removed->key);// 防止内存泄漏delete removed;--size;}}else {// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部DLinkedNode* node = cache[key];node->value = value;moveToHead(node);}}void addToHead(DLinkedNode* node) {node->prev = head;node->next = head->next;head->next->prev = node;head->next = node;}void removeNode(DLinkedNode* node) {node->prev->next = node->next;node->next->prev = node->prev;}void moveToHead(DLinkedNode* node) {removeNode(node);addToHead(node);}DLinkedNode* removeTail() {DLinkedNode* node = tail->prev;removeNode(node);return node;}
};

相关文章:

  • 如何提升演讲能力
  • .net core 6 集成和使用 mongodb
  • UML-顺序图
  • openGauss学习笔记-197 openGauss 数据库运维-常见故障定位案例-分析查询语句是否被阻塞
  • Sublime Text4 crack时替换的汇编指令
  • 时间戳的大小写的坑
  • 深入理解 Flink(五)Flink Standalone 集群启动源码剖析
  • 逻辑回归(解决分类问题)
  • 通过Wireshark抓包分析谈谈DNS域名解析的那些事儿
  • 通过开源端点可见性改善网络安全响应
  • 【React 常用的 TS 类型】持续更新
  • 树莓派4B-Python-使用PCA9685控制舵机云台+跟随人脸转动
  • QT笔记 - 添加项目到版本控制系统 - Git
  • mysql原理--redo日志2
  • 2024,会更好嘛?
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • Flex布局到底解决了什么问题
  • iOS 系统授权开发
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • passportjs 源码分析
  • PermissionScope Swift4 兼容问题
  • SpiderData 2019年2月25日 DApp数据排行榜
  • sublime配置文件
  • ubuntu 下nginx安装 并支持https协议
  • 百度地图API标注+时间轴组件
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 从0实现一个tiny react(三)生命周期
  • 前端面试之CSS3新特性
  • 嵌入式文件系统
  • 实习面试笔记
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 网页视频流m3u8/ts视频下载
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #ifdef 的技巧用法
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (多级缓存)多级缓存
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (六)激光线扫描-三维重建
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (十五)使用Nexus创建Maven私服
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (一)Thymeleaf用法——Thymeleaf简介
  • (一)UDP基本编程步骤
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • *** 2003
  • *Django中的Ajax 纯js的书写样式1
  • . NET自动找可写目录
  • .aanva
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .NET Micro Framework初体验(二)
  • .NET NPOI导出Excel详解