LFU缓存结构设计
题目描述
一个缓存结构需要实现如下功能。
set(key, value):将记录(key, value)插入该结构
get(key):返回key对应的value值
但是缓存结构中最多放K条记录,如果新的第K+1条记录要加入,就需要根据策略删掉一条记录,然后才能把新记录加入。这个策略为:在缓存结构的K条记录中,哪一个key从进入缓存结构的时刻开始,被调用set或者get的次数最少,就删掉这个key的记录;
如果调用次数最少的key有多个,上次调用发生最早的key被删除
这就是LFU缓存替换算法。实现这个结构,K作为参数给出
[要求]
set和get方法的时间复杂度为O(1)
若opt=1,接下来两个整数x, y,表示set(x, y)
若opt=2,接下来一个整数x,表示get(x),若x未出现过或已被移除,则返回-1
对于每个操作2,输出一个答案
代码
import java.util.*;
public class Solution {
/**
* lfu design
* @param operators int整型二维数组 ops
* @param k int整型 the k
* @return int整型一维数组
*/
public int[] LFU (int[][] operators, int k) {
LFUCache cache = new LFUCache(k);
ArrayList<Integer> res = new ArrayList<>();
for (int i = 0; i < operators.length; i++){
if (operators[i][0] == 1){
cache.put(operators[i][1], operators[i][2]);
}else{
res.add(cache.get(operators[i][1]));
}
}
int[] ans = new int[res.size()];
for (int i = 0; i < ans.length; i++){
ans[i] = res.get(i);
}
return ans;
}
public class LFUCache{
//建立节点,存储每个键值对的使用次数
class Node{
int key;
int val;
int freq;
public Node(int key, int val, int freq){
this.key = key;
this.val = val;
this.freq = freq;
}
}
private int capacity;
private int minFreq;
//键值对
private Map<Integer, Node> map = new HashMap<>();
//<次数,使用次数x的Node链表>
private Map<Integer, LinkedList<Node>> freqMap = new HashMap<>();
public LFUCache(int capacity){
this.capacity = capacity;
this.minFreq = 1;
}
public void update(Node node){
//更新Node在freq的次数链表的位置
LinkedList<Node> list = freqMap.get(node.freq);
list.remove(node);
//判断之前次数的链表是否存在
if(list.isEmpty() && node.freq == minFreq) minFreq++;
//更新节点的使用次数
node.freq++;
//更新Node在freqMap中次数链表的位置
if(!freqMap.containsKey(node.freq)) freqMap.put(node.freq, new LinkedList<>());
freqMap.get(node.freq).addLast(node);
}
public int get(int key){
if(!map.containsKey(key)) return -1;
Node node = map.get(key);
update(node);
return node.val;
}
public void put(int key, int val){
//判断是否已经存在Node,存在就更新节点的使用次数
if(map.containsKey(key)){
Node node = map.get(key);
update(node);
return;
}
//判断缓存是否满了,满了就删除使用次数最少的Node,并更新freqMap
if(map.size() >= capacity){
Node node = freqMap.get(minFreq).removeFirst();
map.remove(node.key);
}
//增添新节点,并更新minFreq,freqMap
Node node = new Node(key, val, 1);
map.put(key, node);
if (!freqMap.containsKey(1)){
freqMap.put(1, new LinkedList<>());
}
freqMap.get(1).addLast(node);
minFreq = 1;
}
}
}