力扣LFU缓存题解
题目链接:460. LFU 缓存 - 力扣(LeetCode) (leetcode-cn.com)
参考:Java 13ms 双100% 双向链表 多解法超全😂 - LFU 缓存 - 力扣(LeetCode) (leetcode-cn.com),超详细图解+动图演示 460. LFU缓存 - LFU 缓存 - 力扣(LeetCode) (leetcode-cn.com)
思路:与LRU思路类似,Node结点中增加一个属性freq用于表示该项的使用次数,双向链表与LRU中的一致,LRUCache是Map+双向链表,而LFUCache是Map+Map<freq,双向链表>,因为LRU只需找出最久未使用的Node,而LFU需要找出使用次数最少(如果有多个使用次数最少的,则找出其中最久未使用的)
LRU对照学习
详情请参考另一篇力扣LRU缓存题解
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
| class LRU { DoubleLinkedList list; HashMap<Integer, Node> map; int cap;
public LRU(int cap) { list = new DoubleLinkedList(); map = new HashMap<>(); this.cap = cap; }
public int get(int key) { if (!map.containsKey(key)) { return -1; } int value = map.get(key).value; put(key, value); return value; }
private void put(int key, int value) { Node newNode = new Node(key, value); if (map.containsKey(key)) { list.delete(map.get(key)); } else { if (map.size() > cap) { map.remove(list.delLast()); } } list.addFirst(newNode); map.put(key, newNode); } }
class DoubleLinkedList { Node head; Node tail;
public DoubleLinkedList() { head = new Node(-1, -1); tail = new Node(-1, -1); head.next = tail; tail.prev = head; }
public void addFirst(Node newNode) { newNode.next = head.next; newNode.prev = head; head.next.prev = newNode; head.next = newNode; }
public int delete(Node node) { int res = node.value; node.prev.next = node.next; node.next.prev = node.prev; return res; }
public int delLast() { if (head.next == tail) { return -1; } return delete(tail.prev); } }
class Node { int key; int value; Node prev; Node next;
public Node(int key, int value) { this.key = key; this.value = value; } }
|
LFU
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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
| class LFUCache { HashMap<Integer, DoubleLinkedList> freqMap; HashMap<Integer, Node> map; int cap; int size; int min;
public LFUCache(int capacity) { map = new HashMap<>(); freqMap = new HashMap<>(); this.cap = capacity; size = 0; min = 0; }
public int get(int key) { if (!map.containsKey(key)){ return -1; } Node node = map.get(key); int value = node.value; freqInc(node); return value; }
public void put(int key, int value) { if (cap==0){ return; } Node node = map.get(key); if (node!=null){ node.value=value; freqInc(node); } else { if (size >= cap){ DoubleLinkedList minList = freqMap.get(min); map.remove(minList.tail.prev.key); minList.delLast(); size--; } Node newNode = new Node(key, value); map.put(key,newNode); DoubleLinkedList list = freqMap.get(1); if (list==null){ list = new DoubleLinkedList(); freqMap.put(1,list); } list.addFirst(newNode); size++; min=1; } }
public void freqInc(Node node){ int freq = node.freq; DoubleLinkedList list = freqMap.get(freq); list.delete(node); if (min==freq && list.head.next==list.tail){ min++; } freq++; node.freq++; list = freqMap.get(freq); if (list==null){ list = new DoubleLinkedList(); freqMap.put(freq,list); } list.addFirst(node); } }
class DoubleLinkedList { Node head; Node tail;
public DoubleLinkedList() { head = new Node(-1, -1); tail = new Node(-1, -1); head.next = tail; tail.prev = head; }
public void addFirst(Node newNode) { newNode.prev = head; newNode.next = head.next; head.next.prev = newNode; head.next = newNode; }
public int delete(Node node) { int value = node.value; node.next.prev = node.prev; node.prev.next = node.next; return value; }
public int delLast() { if (head.next == tail) { return -1; } return delete(tail.prev); } }
class Node { int key; int value; Node prev; Node next; int freq;
public Node(int key, int value) { this.key = key; this.value = value; freq = 1; } }
|