描述
设计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]
说明:
输入两个参数:操作数组operators,缓存大小k
操作数组中的元素分为两种:set 和 get
例如:[1,3,2] 1表执行set操作,将键值对"3":2存入缓存
[2,1] 2表执行get操作,获取键"1" 所对应的值
第一次操作后:最常使用的记录为("1", 1) 第二次操作后:最常使用的记录为("2", 2),("1", 1)变为最不常用的 第三次操作后:最常使用的记录为("3", 2),("1", 1)还是最不常用的 第四次操作后:最常用的记录为("1", 1),("2", 2)变为最不常用的 第五次操作后:大小超过了3,所以移除此时最不常使用的记录("2", 2),加入记录("4", 4),并且为最常使用的记录,然后("3", 2)变为最不常使用的记录
备注:
/**
* lru design
* @param operators int整型二维数组 the ops
* @param k int整型 the k
* @return int整型一维数组
*/
function LRU( operators , k ) {
/*
1. 遍历每一个操作
2. 如果是1,则为set操作。先判断当前缓存是否已满,再执行响应的操作
若未满,如果该键已存在,则将其删除,再存入;否则直接存入;
若已满,则移除最久未使用的记录,将其存入
3. 如果是2,则为get操作。
若键不存在,则返回-1;
若存在,读取相应的值,存入结果中,并将读取的记录设置为最常使用
*/
if(operators==null){
return null;
}
let res = []; //存get操作获取的结果
let map = new Map(); //作为LRU缓存结构
for(let i=0; i<operators.length; i++){
// 如果只有两个元素,则只为op和key赋值
let [op, key, value] = operators[i];
//1.set操作
if(op === 1){
//1.1 缓存未满
if(map.size < k){
// 1.1.1 如果已存在该键,将其删除,再重新存入
if(map.has(key)){
map.delete(key);
}
map.set(key,value);
}else{
//1.2 缓存已满
// 1.2.1 删除最久未使用的记录
map.delete(map.keys().next().value);
// 1.2.2 存入当前记录
map.set(key,value);
}
}else if(op === 2){
// 2. get操作
// 2.1 键不存在,返回-1
if(!map.has(key)){
res.push(-1);
}else{
// 2.2 存在,获取对应的值,并将当前键值对更新为最近使用
let cur = map.get(key);
res.push(cur);
map.delete(key);
map.set(key,cur);
}
}
}//for
return res;
}
module.exports = {
LRU : LRU
};
补充:map集合的使用
1、存元素。set()方法,将键值对存入map集合
2、获取所有键。
map.keys() 获取所有的键
3、获取最先存入map的键。
map.keys().next().value 获取第一个键(最先存入map集合的键)
4、删除该键所对应的键值对。
map.delete(map.keys().next().value) 删除第一个键