【LeetCode】146. LRU Cache 解题报告(Python)
作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/lru-cache/
题目描述
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
get(key)- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.put(key, value)- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
The cache is initialized with a positive capacity.
Follow up:
Could you do both operations in O(1) time complexity?
Example:
LRUCache cache = new LRUCache( 2 /* capacity */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4
题目大意
实现一个LRU,LRU全称是Least Recently Used,即最近最久未使用的意思。
LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
题目中给出了LRU的负载大小,当数据被用到的时候变成了最新被使用的,当存放的数据达到了容量上线,需要把最近未被使用的弹出。
解题方法
字典+双向链表
如果看过Java的LinkedHashMap源码,大家都知道可以使用字典+双向链表来实现LRU。
其中双向链表的作用是用来维护使用的顺序的工具,把最近刚使用的放到链表最前面,一直未被使用的放到链表结尾,当达到容量的时候需要把链表结尾节点去除。
大家都知道链表的查找时间复杂度是O(N),题目要求用O(1)的时间复杂度,那么就需要高效的查找方法。我们使用字典来达到这个目的!把链表的每个节点按照{key: node}的方式放入字典里,这样就能通过key快速查到链表节点,从而对该节点进行修改。
综上,我们要对链表实现两个函数:
- 把一个节点从链表中删除(这就是为什么选择双向链表的原因,方便找到前后节点)
- 把一个节点放入链表的头部(需要一个不保存数据的root节点,其prev和next分别指向链表尾部和头部)
这个题中,链表节点需要同时保存key和value。我们通过key在字典找到该节点,返回其val;当要删除一直没被使用过的链表尾部节点时,我们也要从字典中删除它,因此需要知道其key。

python代码如下:
class ListNode:
def __init__(self, key, value):
self.key = key
self.value = value
self.prev = self
self.next = self
class LRUCache:
def __init__(self, capacity: int):
self.dic = dict()
self.capacity = capacity
self.size = 0
self.root = ListNode(0, 0)
def get(self, key: int) -> int:
if key in self.dic:
node = self.dic[key]
self.removeFromList(node)
self.insertIntoHead(node)
return node.value
else:
return -1
def put(self, key: int, value: int) -> None:
if key in self.dic:
node = self.dic[key]
self.removeFromList(node)
self.insertIntoHead(node)
node.value = value
else:
if self.size >= self.capacity:
self.removeFromTail()
self.size -= 1
node = ListNode(key, value)
self.insertIntoHead(node)
self.dic[key] = node
self.size += 1
def removeFromList(self, node):
if node == self.root: return
prev_node = node.prev
next_node = node.next
prev_node.next = next_node
next_node.prev = prev_node
node.prev = node.next = None
def insertIntoHead(self, node):
head_node = self.root.next
head_node.prev = node
node.prev = self.root
self.root.next = node
node.next = head_node
def removeFromTail(self):
if self.size == 0: return
tail_node = self.root.prev
del self.dic[tail_node.key]
self.removeFromList(tail_node)
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
参考资料:https://yikun.github.io/2015/04/03/%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AALRU-Cache%EF%BC%9F/
日期
2019 年 9 月 13 日 —— 今天是中秋节,祝大家中秋快乐
【LeetCode】146. LRU Cache 解题报告(Python)的更多相关文章
- leetcode 146. LRU Cache 、460. LFU Cache
LRU算法是首先淘汰最长时间未被使用的页面,而LFU是先淘汰一定时间内被访问次数最少的页面,如果存在使用频度相同的多个项目,则移除最近最少使用(Least Recently Used)的项目. LFU ...
- Leetcode: LRU Cache 解题报告
LRU Cache Design and implement a data structure for Least Recently Used (LRU) cache. It should supp ...
- Java for LeetCode 146 LRU Cache 【HARD】
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- [LeetCode] 146. LRU Cache 最近最少使用页面置换缓存器
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- [LeetCode] 146. LRU Cache 近期最少使用缓存
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- leetcode@ [146] LRU Cache (TreeMap)
https://leetcode.com/problems/lru-cache/ Design and implement a data structure for Least Recently Us ...
- 【LeetCode】LRU Cache 解决报告
插话:只写了几个连续的博客,博客排名不再是实际"远在千里之外"该.我们已经进入2一万内. 再接再厉.油! Design and implement a data structure ...
- leetcode 146. LRU Cache ----- java
esign and implement a data structure for Least Recently Used (LRU) cache. It should support the foll ...
- Leetcode#146 LRU Cache
原题地址 以前Leetcode的测试数据比较弱,单纯用链表做也能过,现在就不行了,大数据会超时.通常大家都是用map+双向链表做的. 我曾经尝试用C++的list容器来写,后来发现map没法保存lis ...
随机推荐
- R语言与医学统计图形-【15】ggplot2几何对象之线图
ggplot2绘图系统--几何对象之线图 曲线:点连线.路径曲线.时间序列曲线.模型拟合曲线...... 直线:水平直线.垂直直线.斜线. 1.曲线 对象及其参数. #路径图 geom_path(ma ...
- perl中tr的用法(转载)
转载:http://blog.sina.com.cn/s/blog_4a0824490101hncz.html (1)/c表示把匹配不上的字符进行替换. $temp="AAAABCDEF&q ...
- 40-3Sum Closest
3Sum Closest My Submissions QuestionEditorial Solution Total Accepted: 76185 Total Submissions: 2621 ...
- EXCEL-对筛选出(单独手动隐藏行还是在统计范围内)的表格数据进行统计
=SUBTOTAL(3,A1:A5) #计算筛选出的表格中A1:A5中有几个值. =SUBTOTAL(3,I71:I21447) ,在I71:I21447之间计数,会自动略去没有筛选上的隐藏单元格 ...
- Shell 格式化输出printf、awk
目录 Shell 文件的格式化与相关处理 printf.awk 格式化打印printf 案例.格式化输出文件内容 输出命令echo 案例 awk数据处理工具 语法格式 处理流程 AWK内置变量 条件 ...
- 大数据学习day39----数据仓库02------1. log4j 2. 父子maven工程(子spring项目的创建)3.项目开发(埋点日志预处理-json数据解析、清洗过滤、数据集成实现、uid回补)
1. log4j(具体见log4j文档) log4j是一个java系统中用于输出日志信息的工具.log4j可以将日志定义成多种级别:ERROR / WARN / INFO / DEBUG ...
- 大数据学习day14-----第三阶段-----scala02------1. 元组 2.类、对象、继承、特质 3.函数(必须掌握)
1. 元组 映射是K/V对偶的集合,对偶是元组的最简单的形式,元组可以装着多个不同类型的值 1.1 特点 元组相当于一个特殊的数组,其长度和内容都可变,并且数组中可以装任何类型的数据,其主要用处就是存 ...
- 零基础学习java------20---------反射
1. 反射和动态代理 参考博文:https://blog.csdn.net/sinat_38259539/article/details/71799078 1.0 什么是Class: 我们都知道,对象 ...
- Vue3 父子组件通信
1.父传子父组件:在子组件上通过 v-bind绑定属性子组件:先定义下基本类型,然后通过setup的第一个参数取获取传过来的值(详细代码见下面)2.子传父父组件:在子组件上绑定一个事件,并定义回调子组 ...
- keil 报错 expected an identifier
该报错是因为命名重复,可能是因为你加的头文件里面的命名和原程序中的有重复,所以产生了错误.