只个代码由LRU改进得到。
如果每一个频率放在一个LRU里面,每个LRU也有头尾两个指针,指向相邻的LRU。
实际上相邻的LRU可以由frequency = t+1的第一node,可以由frequency = t的最后一个唯一确认。
也就是说,在LRU的设计基础上。我们再多记录一个finalNodes,记录每种频率的尾部就好了。
代码因为情况较多,所以要分析好了,才能归并。
频率可以不连续,最小频率也不一定为1. 我们put(1,1), get(1) LFU里现在只有这个点,频率为2,最小频率不是1.
我们在put(2,2), get(2),get(2), get(2). 2出现了4次。 也就是说频率为2的点1, 指向的下一个是频率为4的点2.
移除node和LRU一样。
添加node,
map里不存在的要加到头部。
2.1 map里存在的点,加到freq + 1尾部的后一个。
2.2 如果刚好freq+1这个频率不存在(也就是freq+1在finalNodes里没有,我们就不需要移动。)
public class LFUCache {
private int capacity;
private int count;
private HashMap<Integer, Tuple> map1; // whether appeared
private HashMap<Integer, Tuple> finalNodes; // value : the final node of key times
private Tuple dummyHead;
private Tuple dummyEnd;
public LFUCache(int capacity) {
this.capacity = capacity;
count = 0;
map1 = new HashMap<Integer, Tuple>();
finalNodes = new HashMap<>();
dummyHead = new Tuple(0, 0, 0);
dummyEnd = new Tuple(0, 0, 0);
dummyHead.next = dummyEnd;
dummyEnd.prev = dummyHead;
}
public int get(int key) {
if (capacity == 0 || !map1.containsKey(key)) {
return -1;
}
Tuple old = map1.get(key);
put(key, old.value);
return old.value;
}
public void put(int key, int value) {
if (capacity == 0) {
return;
}
if (map1.containsKey(key)) { // this key has appeared
Tuple cur = map1.get(key);
if (finalNodes.get(cur.times) == cur && finalNodes.get(cur.times + 1) == null) { // the position should not change
finalNodes.put(cur.times, cur.prev.times == cur.times ? cur.prev : null);
cur.times++;
cur.value = value;
finalNodes.put(cur.times, cur);
return;
}
removeNode(cur); // remove node cur
if (finalNodes.get(cur.times) == cur) {
finalNodes.put(cur.times, cur.prev.times == cur.times ? cur.prev : null);
}
cur.times++;
cur.value = value;
Tuple finalNode = finalNodes.get(cur.times) == null ? finalNodes.get(cur.times - 1) : finalNodes.get(cur.times);
insertNode(finalNode, cur);
finalNodes.put(cur.times, cur);
} else {
if (count == capacity) { // reach limt of the cache
Tuple head = dummyHead.next;
removeNode(head); //remove the first which appeared least times and is the least Used
map1.remove(head.key);
if (finalNodes.get(head.times) == head) {
finalNodes.remove(head.times);
}
} else {
count++;
}
insertHead(key, value);
}
}
public void insertHead(int key, int value) {
Tuple cur = new Tuple(key, value, 1);
if (finalNodes.get(1) == null) {
insertNode(dummyHead, cur);
} else {
Tuple finalNode = finalNodes.get(1);
insertNode(finalNode, cur);
}
finalNodes.put(1, cur);
map1.put(key, cur);
}
public void insertNode(Tuple t1, Tuple t2) {
t2.next = t1.next;
t1.next.prev = t2;
t1.next = t2;
t2.prev = t1;
}
public void removeNode(Tuple node) {
node.next.prev = node.prev;
node.prev.next = node.next;
}
class Tuple {
int key;
int value;
int times;
Tuple prev;
Tuple next;
public Tuple(int key, int value, int times) {
this.key = key;
this.value = value;
this.times = times;
}
}
}
/**
* Your LFUCache object will be instantiated and called as such:
* LFUCache obj = new LFUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。