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
| class LFUCache {
Map<Integer, Node> keyToNode = new HashMap<>(); Map<Integer, Node> freqToDummy = new HashMap<>(); int capacity; int minFreq;
public LFUCache(int capacity) { this.capacity = capacity; }
public int get(int key) { Node node = getNode(key); return node == null ? -1 : node.value; }
public void put(int key, int value) { Node node = getNode(key); if (node != null) { node.value = value; return; } if (keyToNode.size() == capacity) { Node dummy = freqToDummy.get(minFreq); Node backNode = dummy.prev; keyToNode.remove(backNode.key); remove(backNode); if (dummy.prev == dummy) { freqToDummy.remove(minFreq); } } node = new Node(key, value); keyToNode.put(key, node); addFirst(1, node); minFreq = 1; }
private Node getNode(int key) { if (!keyToNode.containsKey(key)) return null; Node node = keyToNode.get(key); remove(node); Node dummy = freqToDummy.get(node.freq); if (dummy.prev == dummy) { freqToDummy.remove(node.freq); if (minFreq == node.freq) { ++minFreq; } } addFirst(++node.freq, node); return node; }
private void addFirst(int freq, Node x) { Node dummy = freqToDummy.computeIfAbsent(freq, k -> newList()); x.prev = dummy; x.next = dummy.next; x.prev.next = x; x.next.prev = x; }
private Node newList() { Node dummy = new Node(0, 0); dummy.prev = dummy; dummy.next = dummy; return dummy; }
private void remove(Node x) { x.next.prev = x.prev; x.prev.next = x.next; }
private static class Node { int key, value, freq; Node prev, next;
public Node(int key, int value) { this.key = key; this.value = value; this.freq = 1; } } }
|