设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能
set(key, value):将记录(key, value)插入该结构
get(key):返回key对应的value值
[要求]
set和get方法的时间复杂度为O(1)
某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。
当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。
若opt=1,接下来两个整数x, y,表示set(x, y)
若opt=2,接下来一个整数x,表示get(x),若x未出现过或已被移除,则返回-1
对于每个操作2,输出一个答案
示例1
输入:
[[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3
复制
返回值:
[1,-1]
复制
说明:
第一次操作后:最常使用的记录为(“1”, 1)
第二次操作后:最常使用的记录为(“2”, 2),(“1”, 1)变为最不常用的
第三次操作后:最常使用的记录为(“3”, 2),(“1”, 1)还是最不常用的
第四次操作后:最常用的记录为(“1”, 1),(“2”, 2)变为最不常用的
第五次操作后:大小超过了3,所以移除此时最不常使用的记录(“2”, 2),加入记录(“4”, 4),并且为最常使用的记录,然后(“3”, 2)变为最不常使用的记录
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
vue中的keep-alive 就是用的这个LRU算法哦
将新数据从尾部插入到this.keys中;
每当缓存命中(即缓存数据被访问),则将数据移到this.keys的尾部;
当this.keys满的时候,将头部的数据丢弃;
LRU的核心思想是如果数据最近被访问过,那么将来被访问的几率也更高,所以我们将命中缓存的组件key重新插入到this.keys的尾部,这样一来,this.keys中越往头部的数据即将来被访问几率越低,所以当缓存数量达到最大值时,我们就删除将来被访问几率最低的数据,即this.keys中第一个缓存的组件。这也就之前加粗强调的已缓存组件中最久没有被访问的实例会被销毁掉的原因所在。
/**
- lru design
- @param operators int整型二维数组 the ops
- @param k int整型 the k
- @return int整型一维数组
*/
function LRU( operators , k ) {
// write code here
this.map = new Map();
// 设置值的时候,如果map里面已经有了,就先删掉,如果大于k了就把最久没有使用的那个删掉,再设置
this.set = function (key, value) {
if (this.map.has(key)) {
this.map.delete(key)
} else {
if (this.map.size === k) {
let keys = this.map.keys()
let key = keys.next().value
this.map.delete(key)
}
}
this.map.set(key, value)
}
// 取值也是一样,遵循‘如果数据最近被访问过,那么将来被访问的几率也更高’的思想,如果一个值需要被取出,我们可以先把他删掉,再重新加入
this.get = function (key) {
if (this.map.has(key)) {
let val = this.map.get(key)
this.map.delete(key)
this.map.set(key,val)
return val
}
return -1
}
let res = []
for (let o of operators) {
if (o[0] === 1) {
this.set(o[1],o[2])
} else if (o[0] === 2) {
res.push(this.get(o[1]))
}
}
return res
}
module.exports = {
LRU : LRU
};