@@ -69,6 +69,18 @@ lfu.get(4); // 返回 4
69
69
70
70
<!-- 这里可写通用的实现逻辑 -->
71
71
72
+ 和 [ LRU 缓存] ( /solution/0100-0199/0146.Lru%20Cache/README.md ) 类似的思路,用 ` map<key, node> ` 和 ` map<freq, list<node>> ` 存储不同使用频率的节点
73
+
74
+ 对于 ` get ` 操作,判断 key 是否存在哈希表中:
75
+
76
+ - 若不存在,返回 -1
77
+ - 若存在,增加节点的使用频率,返回节点值
78
+
79
+ 对于 ` put ` 操作,同样判断 key 是否存在哈希表中:
80
+
81
+ - 若不存在,首先判断缓存容量是否足够,不够的话需要先删除使用次数最少的节点。然后再创建新节点,插入使用频率为 1 的双链表
82
+ - 若存在,修改原节点的值,增加节点的使用频率
83
+
72
84
<!-- tabs:start -->
73
85
74
86
### ** Python3**
@@ -84,7 +96,247 @@ lfu.get(4); // 返回 4
84
96
<!-- 这里可写当前语言的特殊实现逻辑 -->
85
97
86
98
``` java
99
+ class LFUCache {
100
+
101
+ private final Map<Integer , Node > map;
102
+ private final Map<Integer , DoublyLinkedList > freqMap;
103
+ private final int capacity;
104
+ private int minFreq;
105
+
106
+ public LFUCache (int capacity ) {
107
+ this . capacity = capacity;
108
+ map = new HashMap<> (capacity, 1 );
109
+ freqMap = new HashMap<> ();
110
+ }
111
+
112
+ public int get (int key ) {
113
+ if (capacity == 0 ) {
114
+ return - 1 ;
115
+ }
116
+ if (! map. containsKey(key)) {
117
+ return - 1 ;
118
+ }
119
+ Node node = map. get(key);
120
+ incrFreq(node);
121
+ return node. value;
122
+ }
123
+
124
+ public void put (int key , int value ) {
125
+ if (capacity == 0 ) {
126
+ return ;
127
+ }
128
+ if (map. containsKey(key)) {
129
+ Node node = map. get(key);
130
+ node. value = value;
131
+ incrFreq(node);
132
+ return ;
133
+ }
134
+ if (map. size() == capacity) {
135
+ DoublyLinkedList list = freqMap. get(minFreq);
136
+ map. remove(list. removeLast(). key);
137
+ }
138
+ Node node = new Node (key, value);
139
+ addNode(node);
140
+ map. put(key, node);
141
+ minFreq = 1 ;
142
+ }
143
+
144
+ private void incrFreq (Node node ) {
145
+ int freq = node. freq;
146
+ DoublyLinkedList list = freqMap. get(freq);
147
+ list. remove(node);
148
+ if (list. isEmpty()) {
149
+ freqMap. remove(freq);
150
+ if (freq == minFreq) {
151
+ minFreq++ ;
152
+ }
153
+ }
154
+ node. freq++ ;
155
+ addNode(node);
156
+ }
157
+
158
+ private void addNode (Node node ) {
159
+ int freq = node. freq;
160
+ DoublyLinkedList list = freqMap. getOrDefault(freq, new DoublyLinkedList ());
161
+ list. addFirst(node);
162
+ freqMap. put(freq, list);
163
+ }
164
+
165
+ private static class Node {
166
+ int key;
167
+ int value;
168
+ int freq;
169
+ Node prev;
170
+ Node next;
171
+
172
+ Node (int key , int value ) {
173
+ this . key = key;
174
+ this . value = value;
175
+ this . freq = 1 ;
176
+ }
177
+ }
178
+
179
+ private static class DoublyLinkedList {
180
+
181
+ private final Node head;
182
+ private final Node tail;
183
+
184
+ public DoublyLinkedList () {
185
+ head = new Node (- 1 , - 1 );
186
+ tail = new Node (- 1 , - 1 );
187
+ head. next = tail;
188
+ tail. prev = head;
189
+ }
190
+
191
+ public void addFirst (Node node ) {
192
+ node. prev = head;
193
+ node. next = head. next;
194
+ head. next. prev = node;
195
+ head. next = node;
196
+ }
197
+
198
+ public Node remove (Node node ) {
199
+ node. next. prev = node. prev;
200
+ node. prev. next = node. next;
201
+ node. next = null ;
202
+ node. prev = null ;
203
+ return node;
204
+ }
205
+
206
+ public Node removeLast () {
207
+ return remove(tail. prev);
208
+ }
209
+
210
+ public boolean isEmpty () {
211
+ return head. next == tail;
212
+ }
213
+ }
214
+ }
215
+ ```
216
+
217
+ ### ** Go**
218
+
219
+ ``` go
220
+ type LFUCache struct {
221
+ cache map [int ]*node
222
+ freqMap map [int ]*list
223
+ minFreq int
224
+ capacity int
225
+ }
226
+
227
+ func Constructor (capacity int ) LFUCache {
228
+ return LFUCache{
229
+ cache: make (map [int ]*node),
230
+ freqMap: make (map [int ]*list),
231
+ capacity: capacity,
232
+ }
233
+ }
234
+
235
+ func (this *LFUCache ) Get (key int ) int {
236
+ if this.capacity == 0 {
237
+ return -1
238
+ }
239
+
240
+ n , ok := this.cache [key]
241
+ if !ok {
242
+ return -1
243
+ }
244
+
245
+ this.incrFreq (n)
246
+ return n.val
247
+ }
248
+
249
+ func (this *LFUCache ) Put (key int , value int ) {
250
+ if this.capacity == 0 {
251
+ return
252
+ }
253
+
254
+ n , ok := this.cache [key]
255
+ if ok {
256
+ n.val = value
257
+ this.incrFreq (n)
258
+ return
259
+ }
260
+
261
+ if len (this.cache ) == this.capacity {
262
+ l := this.freqMap [this.minFreq ]
263
+ delete (this.cache , l.removeBack ().key )
264
+ }
265
+ n = &node{key: key, val: value, freq: 1 }
266
+ this.addNode (n)
267
+ this.cache [key] = n
268
+ this.minFreq = 1
269
+ }
270
+
271
+ func (this *LFUCache ) incrFreq (n *node ) {
272
+ l := this.freqMap [n.freq ]
273
+ l.remove (n)
274
+ if l.empty () {
275
+ delete (this.freqMap , n.freq )
276
+ if n.freq == this.minFreq {
277
+ this.minFreq ++
278
+ }
279
+ }
280
+ n.freq ++
281
+ this.addNode (n)
282
+ }
283
+
284
+ func (this *LFUCache ) addNode (n *node ) {
285
+ l , ok := this.freqMap [n.freq ]
286
+ if !ok {
287
+ l = newList ()
288
+ this.freqMap [n.freq ] = l
289
+ }
290
+ l.pushFront (n)
291
+ }
292
+
293
+ type node struct {
294
+ key int
295
+ val int
296
+ freq int
297
+ prev *node
298
+ next *node
299
+ }
300
+
301
+ type list struct {
302
+ head *node
303
+ tail *node
304
+ }
305
+
306
+ func newList () *list {
307
+ head := new (node)
308
+ tail := new (node)
309
+ head.next = tail
310
+ tail.prev = head
311
+ return &list{
312
+ head: head,
313
+ tail: tail,
314
+ }
315
+ }
316
+
317
+ func (l *list ) pushFront (n *node ) {
318
+ n.prev = l.head
319
+ n.next = l.head .next
320
+ l.head .next .prev = n
321
+ l.head .next = n
322
+ }
323
+
324
+ func (l *list ) remove (n *node ) {
325
+ n.prev .next = n.next
326
+ n.next .prev = n.prev
327
+ n.next = nil
328
+ n.prev = nil
329
+ }
330
+
331
+ func (l *list ) removeBack () *node {
332
+ n := l.tail .prev
333
+ l.remove (n)
334
+ return n
335
+ }
87
336
337
+ func (l *list ) empty () bool {
338
+ return l.head .next == l.tail
339
+ }
88
340
```
89
341
90
342
### ** ...**
0 commit comments