Skip to content

Commit d63fb27

Browse files
committed
feat: add solutions to lc problem: No.0460
No.0460.LFU Cache
1 parent 3f77695 commit d63fb27

File tree

4 files changed

+728
-0
lines changed

4 files changed

+728
-0
lines changed

solution/0400-0499/0460.LFU Cache/README.md

+252
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@ lfu.get(4); // 返回 4
6969

7070
<!-- 这里可写通用的实现逻辑 -->
7171

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+
7284
<!-- tabs:start -->
7385

7486
### **Python3**
@@ -84,7 +96,247 @@ lfu.get(4); // 返回 4
8496
<!-- 这里可写当前语言的特殊实现逻辑 -->
8597

8698
```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+
}
87336

337+
func (l *list) empty() bool {
338+
return l.head.next == l.tail
339+
}
88340
```
89341

90342
### **...**

0 commit comments

Comments
 (0)