1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| class LFUCache {
static class Node<K, V> { Node<K, V> next; Node<K, V> pre; K k; V v; int freq;
Node(K _k, V _v) { k = _k; v = _v; freq = 1; } }
static class DoublyList {
Node<Integer, Integer> head, tail;
DoublyList() { head = new Node<>(-1, -1); tail = new Node<>(-1, -1); head.next = tail; tail.pre = head; }
boolean isEmpty() { return head.next == tail; }
Node<Integer, Integer> removeFirst() { var node = head.next; var nNode = node.next; head.next = nNode; nNode.pre = head; return node; }
void remove(Node<Integer, Integer> node) { var pNode = node.pre; var nNode = node.next; pNode.next = nNode; nNode.pre = pNode; }
void add(Node<Integer, Integer> node) { var lastNode = tail.pre; lastNode.next = node; node.pre = lastNode; node.next = tail; tail.pre = node; } }
Map<Integer, Node<Integer, Integer>> map = new HashMap<>();
Map<Integer, DoublyList> Freq = new HashMap<>();
int cap;
int cnt;
int minFreq;
public LFUCache(int capacity) { cap = capacity; }
public int get(int key) { if (!map.containsKey(key)) return -1; flush(key); return map.get(key).v; }
public void put(int key, int value) { if (!map.containsKey(key)) { Node<Integer, Integer> node = new Node<>(key, value); if (cnt < cap) cnt++; else removeOne(); map.put(key, node); Freq.computeIfAbsent(1, e -> new DoublyList()).add(node); minFreq = 1; } else { map.get(key).v = value; flush(key); } }
private void flush(int key) { var node = map.get(key); var f = node.freq; var list = Freq.get(f); list.remove(node); if (list.isEmpty() && f == minFreq) minFreq++; node.freq++; Freq.computeIfAbsent(node.freq, e -> new DoublyList()).add(node); }
private void removeOne() { var list = Freq.get(minFreq); Node<Integer, Integer> node = list.removeFirst(); map.remove(node.k); } }
|