运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 `get` 和写入数据 `put` 。 获取数据 `get(key)` - 如果密钥 ( `key` ) 存在于缓存中,则获取密钥的值(总是正数),否则返回 `-1` 。 写入数据 `put(key, value)` - 如果密钥不存在,则写入数据。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据,从而为新数据留出空间。 **进阶:** 你是否可以在 **O(1)** 时间复杂度内完成这两种操作? **示例:** ```js LRUCache cache = new LRUCache( 2 /* 缓存容量 */ ); cache.put(1, 1); cache.put(2, 2); cache.get(1); // 返回 1 cache.put(3, 3); // 该操作会使得密钥 2 作废 cache.get(2); // 返回 -1 (未找到) cache.put(4, 4); // 该操作会使得密钥 1 作废 cache.get(1); // 返回 -1 (未找到) cache.get(3); // 返回 3 cache.get(4); // 返回 4 ``` 附leetcode地址:[leetcode](https://leetcode-cn.com/problems/lru-cache/solution/ping-zi-jun-qian-duan-jin-jie-suan-fa-lru-shi-xian/)
Activity
BoswellJi commentedon Apr 7, 2020
Lostsory commentedon Apr 7, 2020
liwuhou commentedon Apr 7, 2020
感觉对象数组应该挺好实现的,每次调用get方法获取数据或者put方法更新数据,都会将数据队列顺序都更新了,需要注意的是,put方法,需要判断当前队列长度是否超过缓存容量长度、是否是队列中已有的key这些问题,然后做对应操作。
这一切都是基于我理解的这个put方法应该是可以更新原有数据的。
感觉自己想得有些复杂了,多搞个变量来存放key不就好了
uuRRx0 commentedon Apr 7, 2020
sisterAn commentedon Apr 7, 2020
基础解法:数组+对象实现
类 vue keep-alive 实现
进阶:Map
利用 Map 既能保存键值对,并且能够记住键的原始插入顺序
leetcode
BruceYuj commentedon Apr 8, 2020
有定期在 github 更新 leetcode 和其他 OI 里面的题目。欢迎各位 watch 讨论(不用star)。
主要语言为 JavaScript,偶尔会用 Python 或 Java
JavaScript 版 LeetCode 题解
我的 LeetCode 地址
下面给出 JavaScript 版本
思路
在操作系统中, LRU 是一种常用的页面置换算法。其目的在于在发生缺页中断时,将最长时间未使用的页面给置换出去。因此,我们需要算法中的效率足够的高。
由题目可以知道,整个算法会包含以下几个操作:
从上面分析来看,哈希表+双向链表就是 LRU 缓存算法的核心数据结构了。我们使用链表尾部结点来表示最近访问的结点。
细心的读者可能会产生疑问,为什么使用双向链表而不是单向链表?$O(1)$ 时间内获得当前结点的前驱结点。
原因在于,如果想要在常数时间内将链表中间的结点移动到尾部,我们需要能够在
首先,我们设计链表的结点:
细心的读者会发现,我们在设计结点的时候重复存储了 key(哈希表和双向链表中都存储了 key),这又是为什么呢?
这是因为我们在缓存满时需要删除双向链表中的结点以及结点在哈希表中保存的值。如果不在哈希表中存储 key,就无法在哈希表中进行对应的删除了。
代码
[-]leetcode:LRU 缓存机制[/-][+]leetcode146:LRU 缓存机制[/+]zero9527 commentedon Apr 28, 2020
consoles commentedon May 2, 2020
看了下 所有的实现,基本上要么是基于数组的维护key的顺序(这需要O(n)的时间找到key所在的索引),要么依赖map本身能维护插入的顺序:访问的时候key的时候删除key重新加入key,这样这个key就在末尾了最后被淘汰,之前写了个基于双向链表 + 哈希表的,这里提供一个思路:
[-]leetcode146:LRU 缓存机制[/-][+]华为&leetcode146:LRU 缓存机制[/+]george-wq commentedon May 16, 2020
var LRUCache = function(num) {
this.maxNum = num ? num : 2;
this.data = new Map();
}
LRUCache.prototype.get = function(key) {
let value = -1;
if (this.data.get(key)) {
value = this.data.get(key);
this.data.delete(key);
this.put(key, value);
}
return value;
}
LRUCache.prototype.put = function(key, value) {
if (this.data.size === this.maxNum || this.data.get(key)) {
// this.data.delete([...this.data.keys()][0]);
this.data.delete(this.data.keys().next().value);
}
this.data.set(key,value);
}
var cache = new LRUCache(4);
zjhlaap commentedon Jun 3, 2020
WalterBrightHub commentedon Jun 27, 2020
双向链表+Map
cutie6 commentedon Jul 11, 2020
这里应该要 delete cache[key] 吧
Been101 commentedon Jul 13, 2020
Verahuan commentedon Jul 22, 2020
/**
*/
var LRUCache = function(capacity) {
this.capacity=capacity;
this.save=new Map();
this.clear=function(){
while(this.save.size>=this.capacity){
this.save.delete(this.save.keys().next().value)
}
}
};
/**
*/
LRUCache.prototype.get = function(key) {
if(this.save.has(key)){
var val=this.save.get(key);
this.save.delete(key)
this.save.set(key,val)
return val
}
return -1
};
/**
*/
LRUCache.prototype.put = function(key, value) {
if(this.save.has(key)){
this.save.delete(key)
this.save.set(key,value)
}else{
this.clear();
this.save.set(key,value)
}
};
/**
*/
AnranS commentedon Nov 14, 2020
借助javascript Map的特性:map的键是按照set的顺序存储的。
MDN Map.prototype.keys()
DbbHobo commentedon Jan 8, 2021
第一种方法里面,if(this.cache[key])如果值正好是0就有问题了呢~
azl397985856 commentedon Mar 3, 2021
题目地址(146. LRU 缓存机制)
https://leetcode-cn.com/problems/lru-cache/
题目描述
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
实现
LRUCache类:LRUCache(int capacity)以正整数作为容量capacity初始化 LRU 缓存int get(int key)如果关键字key存在于缓存中,则返回关键字的值,否则返回 -1 。void put(int key, int value)如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。进阶:你是否可以在
O(1)时间复杂度内完成这两种操作?示例:
思路
最终采取双向链表 + 哈希表
通过哈希表, 查看传入的关键字对应的链表节点, 是否存在
通过哈希表, 查看传入的关键字对应的链表节点, 是否存在
伪代码如下:
代码
语言支持: JS, Go, PHP, CPP
JS Code:
Go Code:
PHP Code:
CPP Code:
复杂度分析
RyanMeg123 commentedon May 24, 2022
nekobaex commentedon May 2, 2023
liuyu666 commentedon May 31, 2023
add 也属于操作数据,所以每次都要更新下缓存,在
if (cache.size > this.max - 1) {之前判断下cache.has(key),然后从cache中删除AjaxSir commentedon Aug 2, 2023
RainyNight9 commentedon Sep 27, 2023
itouchzh commentedon Apr 9, 2024