Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d63fb27

Browse files
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

Lines changed: 252 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /