java
复制代码
class LFUCache {
// 最小调用频率
int minFreq;
// 容量
int capacity;
// key->key,value->对应节点
Map<Integer, Node> kvMap;
// key->使用频率,value->对应链表的头尾节点
Map<Integer, Node[]> freqMap;
public LFUCache(int capacity) {
minFreq = 0;
this.capacity = capacity;
kvMap = new HashMap<>(capacity);
freqMap = new HashMap<>();
}
public int get(int key) {
if (kvMap.get(key) == null) {
return -1;
}
Node node = kvMap.get(key);
// 当前节点是最低频率且此时最低频率链表只有该节点,最低频率增加
if (node.freq == minFreq && node.prev.prev == null && node.next.next == null) {
minFreq++;
}
// 频率加一
node.freq++;
// 从旧频率对应链表删除
deleteNode(node);
// 插入到新频率链表尾部
if (freqMap.get(node.freq) == null) {
initFreqMap(node.freq);
}
addTail(node, freqMap.get(node.freq)[1]);
return node.value;
}
public void put(int key, int value) {
Node node = new Node();
if (kvMap.get(key) != null) {
node = kvMap.get(key);
// 当前节点是最低频率且此时最低频率只有该节点,最低频率增加
if (node.freq == minFreq && node.prev.prev == null && node.next.next == null) {
minFreq++;
}
// 频率加一
node.freq++;
node.value = value;
// 从旧频率对应链表删除
deleteNode(node);
} else {
// 超出容量,移除最小频率的节点
if (capacity == 0) {
Node head = freqMap.get(minFreq)[0];
kvMap.remove(head.next.key);
deleteNode(head.next);
capacity = 1;
}
node.freq = 1;
node.key = key;
node.value = value;
kvMap.put(key, node);
minFreq = 1;
capacity--;
}
if (freqMap.get(node.freq) == null) {
initFreqMap(node.freq);
}
// 插入到新频率链表尾部
addTail(node, freqMap.get(node.freq)[1]);
}
public void initFreqMap(int freq) {
Node head = new Node();
Node tail = new Node();
head.next = tail;
tail.prev = head;
Node[] arr = new Node[] {head, tail};
freqMap.put(freq, arr);
}
public void deleteNode(Node node) {
Node prevNode = node.prev;
Node nextNode = node.next;
prevNode.next = nextNode;
nextNode.prev = prevNode;
node.prev = null;
node.next = null;
}
public void addTail(Node node, Node tail) {
Node prevNode = tail.prev;
prevNode.next = node;
node.prev = prevNode;
node.next = tail;
tail.prev = node;
}
}
class Node {
int freq;
int key;
int value;
Node prev;
Node next;
}