题目
请你设计并实现一个满足 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) 的平均时间复杂度运行。
示例:
输入
[“LRUCache”, “put”, “put”, “get”, “put”, “get”, “put”, “get”, “get”, “get”]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]
解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
题解
/**
* @param {number} capacity
*/
var LRUCache = function(capacity) {
this.capacity = capacity;
this.map = new Map();
};
/**
* @param {number} key
* @return {number}
*/
LRUCache.prototype.get = function(key) {
if(this.map.has(key)){
let temp=this.map.get(key)
this.map.delete(key);
this.map.set(key, temp);//放在最下面表示最新使用
return temp//temp为值
}else{
return -1
}
};
/**
* @param {number} key
* @param {number} value
* @return {void}
*/
LRUCache.prototype.put = function(key, value) {
if(this.map.has(key)){
this.map.delete(key);
}
this.map.set(key,value);
if(this.map.size > this.capacity){
// 若超出范围,将map中头部的删除
// map.keys()返回一个迭代器
// 迭代器调用next()方法,返回包含迭代器返回的下一个值,在value中
// 这里有个知识点
// map的entries方法,还有keys方法(可以看mdn)),会返回一个迭代器
// 迭代器调用next也是顺序返回,所以返回第一个的值就是最老的,找到并删除即可
this.map.delete(this.map.keys().next().value);
}
};
笔记:
-
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
- 新数据插入到链表头部;
- 每当缓存命中(即缓存数据被访问),则将数据移到链表头部;
- 当链表满的时候,将链表尾部的数据丢弃。
过程如下
- 最开始时,内存空间是空的,因此依次进入A、B、C是没有问题的
- 当加入D时,就出现了问题,内存空间不够了,因此根据LRU算法,内存空间中A待的时间最为久远,选择A,将其淘汰
- 当再次引用B时,内存空间中的B又处于活跃状态,而C则变成了内存空间中,近段时间最久未使用的
- 当再次向内存空间加入E时,这时内存空间又不足了,选择在内存空间中待的最久的C将其淘汰出内存,这时的内存空间存放的对象就是E->B->D
-
用map保存key
1.get 有key 缓存value 删掉key 再set一遍
2.put 有key 删掉 重新set 超出内存 删掉第一个key -
迭代器是通过使用
next()
方法实现 Iterator protocol 的任何一个对象,该方法返回具有两个属性的对象:value
,这是序列中的 next 值;和done
,如果已经迭代到序列中的最后一个值,则它为true
。如果value
和done
一起存在,则它是迭代器的返回值。 -
js的map的put方法
-
js中的Map.set()相当于java中的Map.put(),
js中的Map.size相当于java中的Map.size();//在js中size是属性,在Map中size()是方法。