需要注意的是:又要存操作数,又要存相同的操作数最古老的那一个,所以需要使用的是复合的数据结构。
代码来源:
https://leetcode-cn.com/problems/lfu-cache/solution/java-13ms-shuang-100-shuang-xiang-lian-biao-duo-ji/
package test0309;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
public class LFUCache1 {
Map<Integer, Node> cache;
Map<Integer, LinkedHashSet<Node>> freqMap;
int size;
int capacity;
int min;
public LFUCache1(int capacity){
this.capacity = capacity;
cache = new HashMap<>(capacity);
freqMap = new HashMap<>();
}
public int get(int key){
Node node = cache.get(key);
if (node == null){
return -1;
}
freqInc(node);//操作数 + 1,但是实际上是使原来操作数的set删掉这个node,
// 再把node的freq + 1,添加到(freq+1)的set中,最古老操作数当然会被在遍历时第一个删除。
return node.value;
}
public void put(int key,int value){
if (capacity == 0){
return;
}
Node node = cache.get(key);
if (node != null){
//存在就更新
node.value = value;
freqInc(node);
} else {
if (size == capacity){
//满了
Node deadNode = removeNode();
cache.remove(deadNode.key);
size--;
}
//再添加
Node newNode = new Node(key,value);
cache.put(key,newNode);
//往双向链表中添加新的节点
addNode(newNode);
size++;
}
}
private void addNode(Node newNode) {
LinkedHashSet<Node> set = freqMap.get(1);
if (set == null){
set = new LinkedHashSet<Node>();
set.add(newNode);
freqMap.put(1,set);
}
set.add(newNode);
min = 1;
}
private Node removeNode() {
LinkedHashSet<Node> set = freqMap.get(min);
//最古老没有操作的那个
Node deadNode = set.iterator().next();
set.remove(deadNode);
return deadNode;
}
private void freqInc(Node node) {
//更新当前key对应的频次
//因为当前节点的操作数已经改变,就需要把它从当前操作数的set中删除
int freq = node.freq;
LinkedHashSet<Node> set = freqMap.get(freq);
set.remove(node);
if (freq == min && set.size() == 0){
min = freq + 1;
}
//节点的操作数更新
node.freq++;
LinkedHashSet<Node> newSet = freqMap.get(freq + 1);
if (newSet == null){
newSet = new LinkedHashSet<>();
freqMap.put(freq + 1,newSet);
}
newSet.add(node);
}
}
package test0309;
import java.util.HashMap;
import java.util.Map;
public class LFUCache2 {
Map<Integer,Node> cache;
Map<Integer,DoublyLinkedList> freqMap;
int size;
int capacity;
int min;
public LFUCache2(int capacity){
this.capacity = capacity;
cache = new HashMap<>(capacity);
freqMap = new HashMap<>();
}
public int get(int key){
Node node = cache.get(key);
if (node == null){
return -1;
}
freqInc(node);
return node.value;
}
public void put(int key,int value){
if (capacity == 0){
return;
}
Node node = cache.get(key);
if (node != null){
//有这个key,就更新
node.value = value;
//操作数加1
freqInc(node);
} else {
if (size == capacity){
DoublyLinkedList minList = freqMap.get(min);
cache.remove(minList.tail.pre.key);
minList.removeNode(minList.tail.pre);
size--;
}
Node newNode = new Node(key,value);
cache.put(key,newNode);
DoublyLinkedList list = freqMap.get(1);
if (list == null){
list = new DoublyLinkedList();
freqMap.put(1,list);
}
list.addNode(newNode);
size++;
min = 1;
}
}
private void freqInc(Node node) {
//从对应的列表中移除
int freq = node.freq;
DoublyLinkedList list = freqMap.get(freq);
list.removeNode(node);
if (freq == min && list.head.post == list.tail){
min = freq + 1;
}
node.freq++;
DoublyLinkedList newList = freqMap.get(freq + 1);
if (newList == null){
newList = new DoublyLinkedList();
freqMap.put(freq + 1,newList);
}
newList.addNode(node);
}
public static void main(String[] args) {
LFUCache2 cache2 = new LFUCache2(2);
cache2.put(1,1);
}
}