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
|
type KVNode struct {
prev, next *KVNode
key, value int
freq int
}
type DoubleList struct {
head, tail *KVNode
size int
}
func NewDoubleList() *DoubleList {
dl := &DoubleList{
head: &KVNode{ key: 0, value: 0},
tail: &KVNode{ key: 0, value: 0},
size: 0,
}
dl.head.next = dl.tail
dl.tail.prev = dl.head
return dl
}
func (dl *DoubleList) PushFront(node *KVNode) {
node.prev = dl.head
node.next = dl.head.next
dl.head.next.prev = node
dl.head.next = node
dl.size++
}
func (dl *DoubleList) RemoveBack() *KVNode {
lastNode := dl.tail.prev
dl.Remove(lastNode)
return lastNode
}
func (dl *DoubleList) Remove(node *KVNode) {
node.prev.next = node.next
node.next.prev = node.prev
dl.size--
}
type LFUCache struct {
cache map[int]*KVNode
freq map[int]*DoubleList
capacity, size, minFreq int
}
func Constructor(capacity int) LFUCache {
return LFUCache{
cache: map[int]*KVNode{},
freq: map[int]*DoubleList{},
capacity: capacity,
size: 0,
minFreq: 0,
}
}
func (lfu *LFUCache) IncFreq(node *KVNode) {
preFreq := node.freq
lfu.freq[preFreq].Remove(node)
if preFreq == lfu.minFreq && lfu.freq[preFreq].size == 0 {
lfu.minFreq++
delete(lfu.freq, preFreq)
}
node.freq++
if lfu.freq[node.freq] == nil {
lfu.freq[node.freq] = NewDoubleList()
}
lfu.freq[node.freq].PushFront(node)
}
func (lfu *LFUCache) Get(key int) int {
if node, ok := lfu.cache[key]; ok {
lfu.IncFreq(node)
return node.value
}
return -1
}
func (lfu *LFUCache) Put(key int, value int) {
if lfu.capacity == 0 {
return
}
if node, ok := lfu.cache[key]; ok {
node.value = value
lfu.IncFreq(node)
return
}
if lfu.size == lfu.capacity {
node := lfu.freq[lfu.minFreq].RemoveBack()
delete(lfu.cache, node.key)
lfu.size--
// No need to update minFreq because it will be set 1 below
}
node := &KVNode{ key: key, value: value, freq: 1}
lfu.cache[key] = node
if lfu.freq[1] == nil {
lfu.freq[1] = NewDoubleList()
}
lfu.freq[1].PushFront(node)
lfu.minFreq = 1
lfu.size++
}
|