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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| class LFUCache { int minfreq, capacity; Map<Integer, Node> keyTable; Map<Integer, DoublyLinkedList> freqTable;
public LFUCache(int capacity) { this.minfreq = 0; this.capacity = capacity; keyTable = new HashMap<Integer, Node>(); freqTable = new HashMap<Integer, DoublyLinkedList>(); } public int get(int key) { if (capacity == 0) { return -1; } if (!keyTable.containsKey(key)) { return -1; } Node node = keyTable.get(key); int val = node.val, freq = node.freq; freqTable.get(freq).remove(node); if (freqTable.get(freq).size == 0) { freqTable.remove(freq); if (minfreq == freq) { minfreq += 1; } } DoublyLinkedList list = freqTable.getOrDefault(freq + 1, new DoublyLinkedList()); list.addFirst(new Node(key, val, freq + 1)); freqTable.put(freq + 1, list); keyTable.put(key, freqTable.get(freq + 1).getHead()); return val; } public void put(int key, int value) { if (capacity == 0) { return; } if (!keyTable.containsKey(key)) { if (keyTable.size() == capacity) { Node node = freqTable.get(minfreq).getTail(); keyTable.remove(node.key); freqTable.get(minfreq).remove(node); if (freqTable.get(minfreq).size == 0) { freqTable.remove(minfreq); } } DoublyLinkedList list = freqTable.getOrDefault(1, new DoublyLinkedList()); list.addFirst(new Node(key, value, 1)); freqTable.put(1, list); keyTable.put(key, freqTable.get(1).getHead()); minfreq = 1; } else { Node node = keyTable.get(key); int freq = node.freq; freqTable.get(freq).remove(node); if (freqTable.get(freq).size == 0) { freqTable.remove(freq); if (minfreq == freq) { minfreq += 1; } } DoublyLinkedList list = freqTable.getOrDefault(freq + 1, new DoublyLinkedList()); list.addFirst(new Node(key, value, freq + 1)); freqTable.put(freq + 1, list); keyTable.put(key, freqTable.get(freq + 1).getHead()); } } }
class Node { int key, val, freq; Node prev, next;
Node() { this(-1, -1, 0); }
Node(int key, int val, int freq) { this.key = key; this.val = val; this.freq = freq; } }
class DoublyLinkedList { Node dummyHead, dummyTail; int size;
DoublyLinkedList() { dummyHead = new Node(); dummyTail = new Node(); dummyHead.next = dummyTail; dummyTail.prev = dummyHead; size = 0; }
public void addFirst(Node node) { Node prevHead = dummyHead.next; node.prev = dummyHead; dummyHead.next = node; node.next = prevHead; prevHead.prev = node; size++; }
public void remove(Node node) { Node prev = node.prev, next = node.next; prev.next = next; next.prev = prev; size--; }
public Node getHead() { return dummyHead.next; }
public Node getTail() { return dummyTail.prev; } }
|