LRU 缓存 -- 哈希链表
相关题目
146. LRU 缓存
要让 put 和 get ⽅法的时间复杂度为 O(1),我们可以总结出 cache 这个数据结构必要的条件:
1、显然 cache 中的元素必须有时序,以区分最近使⽤的和久未使⽤的数据,当容量满了之后要删除最久未使⽤的那个元素腾位置。
2、我们要在 cache 中快速找某个 key 是否已存在并得到对应的 val。
3、每次访问 cache 中的某个 key,需要将这个元素变为最近使⽤的,也就是说 cache 要⽀持在任意位置快速插⼊和删除元素。
哈希表查找快,但是数据⽆固定顺序;链表有顺序之分,插⼊删除快,但是查找慢,所以结合⼆者的⻓处,可以形成⼀种新的数据结构:哈希链表 LinkedHashMap
在Python中,可以使用collections模块中的OrderedDict类来实现类似于Java中LinkedHashMap的功能。
本文最后还提供了一种 结合双向链表和哈希表的 从零开始的实现,供参考。
// 使用 LinkedHashMap 实现
class LRUCache {int cap;LinkedHashMap<Integer, Integer> cache = new LinkedHashMap<>();public LRUCache(int capacity) {this.cap = capacity;}public int get(int key) {if (!cache.containsKey(key)) {return -1;}// 将 key 变为最近使⽤makeRecently(key);return cache.get(key);}public void put(int key, int val) {if (cache.containsKey(key)) {// 修改 key 的值cache.put(key, val);// 将 key 变为最近使⽤makeRecently(key);return;}if (cache.size() >= this.cap) {// 链表头部就是最久未使⽤的 keyint oldestKey = cache.keySet().iterator().next();cache.remove(oldestKey);}// 将新的 key 添加链表尾部cache.put(key, val);}private void makeRecently(int key) {int val = cache.get(key);// 删除 key,重新插⼊到队尾cache.remove(key);cache.put(key, val);}
}
# 使用 OrderedDict 实现
from collections import OrderedDictclass LRUCache:def __init__(self, capacity: int):self.cc = capacityself.d = OrderedDict()def get(self, key: int) -> int:if key in self.d:self.d.move_to_end(key)return self.d[key]return -1def put(self, key: int, value: int) -> None:if key in self.d:del self.d[key]self.d[key] = valueif len(self.d) > self.cc:self.d.popitem(last=False)
# 手撸LRU算法,结合双向链表和哈希表,LinkedHashMap
# 先定义双向链表节点
class DoubleListNodeLRU:next, last = None, Nonedef __init__(self, k, v):self.k = kself.v = vclass NodeLRU:head, tail = None, Nonesize = Nonedef __init__(self):# head tail 为 头尾虚拟节点self.head = DoubleListNodeLRU(0, 0)self.tail = DoubleListNodeLRU(0, 0)self.head.next = self.tailself.tail.last = self.headself.size = 0# 链表尾部添加节点 时间 O(1)def addLast(self, x: DoubleListNodeLRU):x.last = self.tail.lastx.next = self.tailself.tail.last.next = xself.tail.last = xself.size += 1# 删除链表中的 x 节点(x ⼀定存在)# 由于是双链表且给的是⽬标Node节点,时间O(1)def remove(self, x: DoubleListNodeLRU):x.last.next = x.nextx.next.last = x.lastself.size -= 1# 删除链表中第⼀个节点,并返回该节点,时间 O(1)def removeFirst(self):if self.head.next == self.tail:return Nonefirst = self.head.nextself.remove(first)return firstclass LRUCache:def __init__(self, capacity: int):self.cap = capacity# key -> node(key, val)self.map = dict()self.cache = NodeLRU()# 将某个 key 提升为最近使⽤的def makeRecently(self, k):node = self.map.get(k)self.cache.remove(node)self.cache.addLast(node)# 添加最近使⽤的元素def addRecently(self, k, v):node = DoubleListNodeLRU(k, v)self.cache.addLast(node)self.map[k] = node# 删除某⼀个 keydef deletekey(self, k):node = self.map[k]self.map.pop(k)self.cache.remove(node)def removeLeastRecently(self):deleteNode = self.cache.removeFirst()deletekey = deleteNode.kself.map.pop(deletekey)def get(self, k):if k not in self.map:return -1self.makeRecently(k)return self.map.get(k).vdef put(self, k, v):if k in self.map:self.deletekey(k)self.addRecently(k, v)returnif self.cache.size == self.cap:self.removeLeastRecently()self.addRecently(k, v)
相关文章:
LRU 缓存 -- 哈希链表
相关题目 146. LRU 缓存 要让 put 和 get ⽅法的时间复杂度为 O(1),我们可以总结出 cache 这个数据结构必要的条件: 1、显然 cache 中的元素必须有时序,以区分最近使⽤的和久未使⽤的数据,当容量满了之后要删除最久未使⽤的那个元…...

DWC数字世界大会先导论坛将于10月13日在宁波举办 | 数字技术赋能世界可持续发展
农业经济影响世界数千年,工业经济从欧美发源开始已有数百年,数字经济作为世界未来发展之大势,将成为影响未来数百年的世界命题。在以中国式现代化全面推进中华民族伟大复兴的历史征程中,数字技术、数字经济作为中国式现代化实践最…...

Springboot实现登录功能(token、redis、登录拦截器、全局异常处理)
登录流程: 1、前端调用登录接口,往接口里传入账号,密码 2、根据账号判断是否有这个用户,如果有则继续判断密码是否正确 3、验证成功后,则是根据账号,登录时间生成token(用JWT) 4、将…...

AI工程化—— 如何让AI在企业多快好省的落地?
文章目录 前言内容简介读者对象专家推荐目录赠书活动 前言 作为计算机科学的一个重要领域,机器学习也是目前人工智能领域非常活跃的分支之一。机器学习通过分析海量数据、总结规律,帮助人们解决众多实际问题。随着机器学习技术的发展,越来越多…...
mysqld_multi测试
mysqld_multi测试 mysql版本:5.7.25-log 在OS上分别安装了两套mysql, data目录为/mysql/mysql3306、 /mysql/mysql3307 。 端口分别为3306 、3307 配置文件为: /mysql/mysql3306/my.cnf /mysql/mysql3307/my.cnf 参考文档: htt…...
MDC方式实现简单链路追踪
MDC 方式实现日志链路追踪 拦截器 package com.cdn.log.interceptor;import com.cdn.log.consts.CLogConst; import com.cdn.log.utils.IdUtil; import org.slf4j.MDC; import org.springframework.util.StringUtils; import org.springframework.web.servlet.ModelAndView; im…...

Linux深度学习:除基本命令操作外的实用操作
Linux深度学习:除基本命令操作外的实用操作 软件安装systemctl软连接日期、时区IP地址、主机名网络传输下载和网络请求端口 进程管理主机状态系统资源监控磁盘信息监控网络状态监控 环境变量上传、下载压缩、解压root用户、用户、用户组管理查看、修改权限控制 软件…...

app对接广告变现平台:影响app广告单价的4大因素
在移动应用开发者和媒体公司竞相寻求提高广告变现效率的今天,理解影响APP广告单价的关键因素至关重要。广告单价是广告收入的核心组成部分,它受多种因素的影响,直接关系到媒体的盈利能力。主要因素大概有以下几点:#APP广告变现# …...

【数字化转型】10大数字化转型能力成熟度模型01(IOMM)
一、前言 数字化转型是数据化能力建设的目标和价值,作为一个新兴的课题,目前为止并未出现一个统一的数字化转型成熟度模型。不同的企业和机构,根据自身的发展和认知,推出了自己的企业级或者准行业级标准。这些标准具有很强的参考意…...

2023腾讯云轻量应用服务器和普通服务器有什么区别?
腾讯云轻量服务器和云服务器有什么区别?为什么轻量应用服务器价格便宜?是因为轻量服务器CPU内存性能比云服务器CVM性能差吗?轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境,云服务器CV…...

SSL证书是什么?1分钟get
在当今互联网世界中,保护数据的完整性和隐私性至关重要,由此,在网络数据安全保护领域,作为保护网络传输数据安全的SSL证书越来越频繁出现。那么你知道SSL证书是什么?SSL证书有哪些类型?SSL证书有什么用吗&a…...

3D打印机升级killpper
本来是想整台新机的,但是想想老机器4max也不能就此放弃,看了看视频,改装升级似乎也没有那么难。然后就是换了喷头、皮带、轴承、挤出机、打印平台、加热板等等。做了干燥箱,改装挤出机结构来适配,风扇口也一并搞掉&…...

源码编译dotnetcore的runtime
为了dotnetcore运行时的安可目标,特意在国庆假期研究了怎么编译dotnetcore的runtime。由于我们用的是.net6,最新的是8,所以从github下载的.net6的分支代码进行的编译。查遍了国内外资料,估计微软服务太体贴了,竟然没什…...

11个在线免费调整图像大小而不会降低质量工具
图片对于增强您的网站、博客和其他在线平台的视觉效果非常重要,而这些图片的正确尺寸在这里起着重要作用。如果您有多种尺寸的图像并且想要调整为一个尺寸,可以使用多种在线图像调整工具。使用在线工具,没有软件下载或安装的麻烦,…...

聊聊机器的情感和意识
这是鼎叔的第七十七篇原创文章。行业大牛和刚毕业的小白,都可以进来聊聊。 欢迎关注本公众号《敏捷测试转型》,星标收藏,大量原创思考文章陆续推出。 鼎叔的个人专著《无测试组织-测试团队的敏捷转型》无测试组织:测试团队的敏捷…...
职责链模式,非常容易被忽视的设计模式之一(设计模式与开发实践 P13)
文章目录 现实实例反例优化异步职责链 职责链模式在 C# 中是常见的,他的定义是:使多个对象都有机会处理请求,从而避免发送者和请求者之间的耦合关系,将对象连成一条链并传递该请求,直到有一个对象处理它为止 现实实例…...

架构师选择题--计算机网络
架构师选择题--计算机网络 22年考题21年考题 22年考题 d http:80 https:httpssl :443 b b pop3是邮件接收协议:110 SMTP是邮件发送协议:25 http:80 A 网络隔离:防火墙(逻辑),网闸(物…...
【图论】Linova and Kingdom—CF1336A
Linova and Kingdom—CF1336A 参考文章 思路 1 1 1 号节点为根节点。很容易想到,工业城市在树的下边,旅游城市在树的上边。具体来说,如果节点 u u u 是工业城市,那么它的子树的所有节点一定都是工业城市;如果节点 u…...

【红日靶场】vulnstack3-完整渗透过程
系列文章目录 【红日靶场】vulnstack1-完整渗透过程 【红日靶场】vulnstack2-完整渗透过程 【红日靶场】vulnstack3-完整渗透过程 文章目录 系列文章目录基本信息环境配置开始渗透信息收集暴力破解漏洞利用绕过内网信息收集尝试上线msf上线msf横向移动msf 传达会话给cs横向到域…...
物联网通信技术课程作业资料(TPUNB技术)
参考内容 TPUNB无线通信技术 - 技象科技 (techphant.cn) 技象科技CTO郑凛:用最好的物联网服务最多的人 | 了不起的创变者_技术_通信_团队 (sohu.com) LPWAN技术融合使用大势之下,TPUNB奔跑的一年-IOTE物联网展 (baidu.com) 院士认可国际首创…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...