面试必考真题-算法篇 牛客网
模拟 LRU缓存结构
题目描述
设计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 (最近最少使用)
本题提示了可供操作的两种方法get和set,而数据类型是key-value模式的,自然想到Map类型去实现;
其次,对最近读取的值(题目要求保存到数组返回),和最近set的值,都是LRU值,那么关键点有两个:
1.在于当map容量达到k值的时候,如果set,需要删除最初保存的值同时put进去最新的值。
2.get获取LRU的map里的值,如果没有,返回-1,存在则返回key对应value,同时要删除key之前在map里面的位置,使用put放入这对key-value。
根据LinkedHashMap的特性,知道他的key是按照顺序存放的,这样删除第一个放进去的值(最不常用的值)很方便。
下面是Java代码
import java.util.*;
public class Solution {
/**
* lru design
* @param operators int整型二维数组 the ops
* @param k int整型 the k
* @return int整型一维数组
*/
public int[] LRU (int[][] operators, int k) {
// write code here
LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>();
ArrayList<Integer> list= new ArrayList<>();
for(int i = 0 ; i < operators.length ; i++){
Integer opt = operators[i][0],key = operators[i][1];
if(opt == 1){ //set
if(map.containsKey(key)){
map.remove(key);
}else{
//当超出缓存大小后,由于map中的数据是已经排序好的,所以直接将keySet的第一位移除即可。
if(map.size() == k){
map.remove(map.keySet().toArray()[0]);
}
}
map.put(key,operators[i][2]);
}else if(opt == 2){//get
if(map.containsKey(key)){
int val = map.remove(key);
map.put(key,val);
list.add(map.get(key));
}else{
list.add(-1);
}
}
}
int[] arr = new int[list.size()];
for(int i = 0 ; i < arr.length ; i++){
arr[i] = list.get(i);
}
return arr;
}
}