import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
class LFUCache {
static class Node {
private int key;
private int value;
private int frequency;
private Node pre;
private Node next;
}
static class DoubleList {
private Node first;
private Node last;
private int size = 0;
public int size() {
return this.size;
}
public Node removeLast() {
Node l = last;
return unlinkLast(l);
}
public void addFirst(Node node) {
linkFirst(node);
}
private void linkFirst(Node node) {
Node f = first;
node.next = f;
first = node;
if (f == null) {
last = node;
} else {
f.pre = node;
}
size++;
}
private Node unlinkLast(Node l) {
Node pre = l.pre;
l.pre = null;
last = pre;
if (pre == null) {
first = null;
} else {
pre.next = null;
}
size--;
return l;
}
public void unlinkNode(Node node) {
Node next = node.next;
Node pre = node.pre;
if (pre == null) {
first = next;
} else {
pre.next = next;
node.pre = null;
}
if (next == null) {
last = pre;
} else {
next.pre = pre;
node.next = null;
}
size--;
}
}
private int capacity;
private Map<Integer, Node> dataMap = new HashMap<>();
private Map<Integer, DoubleList> frequencyMap = new TreeMap<>();
public LFUCache(int capacity) {
this.capacity = capacity;
}
public int get(int key) {
Node node = dataMap.get(key);
if (node != null) {
incrementFrequency(node);
return node.value;
}
return -1;
}
public void put(int key, int value) {
if (this.capacity <= 0) {
return;
}
Node node = dataMap.get(key);
if (node != null) {
node.value = value;
incrementFrequency(node);
return;
}
node = new Node();
node.key = key;
node.value = value;
node.frequency = 1;
if (dataMap.size() >= capacity) {
Map.Entry<Integer, DoubleList> firstEntry = frequencyMap.entrySet().iterator().next();
Node removedNode = firstEntry.getValue().removeLast();
if (firstEntry.getValue().size() == 0) {
frequencyMap.remove(firstEntry.getKey());
}
dataMap.remove(removedNode.key);
}
dataMap.put(key, node);
DoubleList accessList = frequencyMap.computeIfAbsent(node.frequency, a -> new DoubleList());
accessList.addFirst(node);
}
public void incrementFrequency(Node node) {
DoubleList oldAccessList = frequencyMap.get(node.frequency);
oldAccessList.unlinkNode(node);
if (oldAccessList.size == 0) {
frequencyMap.remove(node.frequency);
}
node.frequency++;
DoubleList newAccessList = frequencyMap.computeIfAbsent(node.frequency, a -> new DoubleList());
newAccessList.addFirst(node);
}
}
public class Solution {
public static void main(String[] args) {
LFUCache cache = new LFUCache(2);
cache.put(1, 1);
cache.put(2, 2);
System.out.println(cache.get(1));
cache.put(3, 3);
System.out.println(cache.get(2));
System.out.println(cache.get(3));
cache.put(4, 4);
System.out.println(cache.get(1));
System.out.println(cache.get(3));
System.out.println(cache.get(4));
}
}
本算法时间复杂度O(logn),另一种实现思路,时间复杂度O(1):