实现一个简单的LRU(最近最少使用)缓存,并解释其实现原理和时间复杂度。
6条回答 默认 最新
- JJJ69 2024-04-18 12:06关注
实现一个简单的LRU(Least Recently Used,最近最少使用)缓存通常涉及使用数据结构如双向链表和哈希表来高效地跟踪和更新缓存项。下面是一个Python实现示例:
import collections class LRUCache: def __init__(self, capacity: int): self.capacity = capacity self.cache = collections.OrderedDict() # 使用OrderedDict实现双向链表功能 self.size = 0 def get(self, key: int) -> int: if key not in self.cache: return -1 value = self.cache.pop(key) # 移除旧位置的键值对,触发其移动到链表末尾 self.cache[key] = value # 重新插入,更新访问时间 return value def put(self, key: int, value: int) -> None: if key in self.cache: self.cache.pop(key) # 移除旧位置的键值对,触发其移动到链表末尾 self.cache[key] = value # 插入新的键值对,自动位于链表末尾 self.size += 1 if self.size > self.capacity: # 若超出容量,移除最不常使用的元素(即链表头部) self.cache.popitem(last=False) self.size -= 1
实现原理:
**使用collections.OrderedDict**:OrderedDict是一个有序字典,它在保持键值对关系的同时,还能记住元素的插入顺序。当访问或修改元素时,它会自动调整元素在内部链表中的位置,使得最新访问或插入的元素始终位于链表末尾。这恰好符合LRU缓存的需求,即最近访问或插入的元素应该是最“新”的。 get操作:当查询某个键时,如果键存在,则将其对应的值从字典中移除(这会使该键值对移动到链表末尾),然后立即重新插入(更新访问时间)。这样,无论查询成功还是失败,被查询的键都会成为最近访问的元素。如果键不存在,则返回默认值(此处为-1)。 put操作:插入一个新的键值对。如果键已存在,则先移除旧的键值对(更新访问时间),再插入新的。插入新键值对后,其自动位于链表末尾。若此时缓存容量超过设定的上限,通过调用popitem(last=False)移除链表头部(即最不常访问的)元素,从而保证缓存大小不超过capacity。
时间复杂度分析:
get操作: 查找键是否存在:O(1),因为OrderedDict提供了O(1)的查找时间复杂度。 移除并重新插入键值对:由于OrderedDict内部的优化,这两个操作合起来的时间复杂度也是O(1)。 put操作: 插入键值对:同上,O(1)。 检查并可能移除最不常使用的元素:在最坏情况下(即每次插入都需要移除一个元素),popitem(last=False)的时间复杂度为O(1)。
综上所述,此简单LRU缓存的get和put操作均具有O(1)的时间复杂度,实现了高效的缓存访问和更新。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 1无用
悬赏问题
- ¥15 不知道是该怎么引用多个函数片段
- ¥15 pip install后修改模块路径,import失败,需要在哪里修改环境变量?
- ¥15 爬取1-112页所有帖子的标题但是12页后要登录后才能 我使用selenium模拟登录 账号密码输入后 会报错 不知道怎么弄了
- ¥30 关于用python写支付宝扫码付异步通知收不到的问题
- ¥50 vue组件中无法正确接收并处理axios请求
- ¥15 隐藏系统界面pdf的打印、下载按钮
- ¥15 MATLAB联合adams仿真卡死如何解决(代码模型无问题)
- ¥15 基于pso参数优化的LightGBM分类模型
- ¥15 安装Paddleocr时报错无法解决
- ¥15 python中transformers可以正常下载,但是没有办法使用pipeline