牛客网: BM101
题目: 设计实现LFU
思路: 在LRU基础上,将双端队列拆开,存储在以频率为key的map中,每次访问时,需要增加节点的频率 incFreq(node),当node.freq所在map对应的双端队列为空时,需在map中删除此freq信息;添加缓存时,如果已有的话,则需调用incFreq, 否则判断容量size与capacity关系,删除minFreq对应的双端队列的队头,同时将新结点添加到freq=1对应的双端队列队尾
代码:
// go
package main
// import "fmt"
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* lfu design
* @param operators int整型二维数组 ops
* @param k int整型 the k
* @return int整型一维数组
*/
type Node struct {
key, val int
pre, next *Node
freq int
}
type DoubleLinkedList struct {
head, tail *Node
}
func initDoubleLinkedList() *DoubleLinkedList {
head, tail := &Node{}, &Node{}
head.next = tail
tail.pre = head
return &DoubleLinkedList{
head: head,
tail: tail,
}
}
func (this *DoubleLinkedList) AddLast(node *Node) {
node.pre =this.tail.pre
node.pre.next = node
node.next = this.tail
this.tail.pre = node
}
func (this *DoubleLinkedList) Remove(node *Node) {
node.pre.next = node.next
node.next.pre = node.pre
node.next = nil
node.pre = nil
}
func (this *DoubleLinkedList) IsEmpty() bool {
return this.head.next == this.tail
}
func (this *DoubleLinkedList) RemoveFirst() *Node {
if this.IsEmpty() {
return nil
}
first := this.head.next
this.Remove(first)
return first
}
type Solution struct {
cache map[int]*Node
freq map[int]*DoubleLinkedList
capacity, size, minFreq int
}
func Constructor(capacity int) Solution {
lfuCache := Solution{
cache: map[int]*Node{},
freq: map[int]*DoubleLinkedList{},
capacity: capacity,
}
return lfuCache
}
func (this *Solution) Get(key int) int {
node, exist := this.cache[key]
if !exist {
return -1
}
this.IncFreq(node)
return node.val
}
func (this *Solution) IncFreq(node *Node) {
_freq := node.freq
this.freq[_freq].Remove(node)
if this.minFreq == _freq && this.freq[_freq].IsEmpty() {
this.minFreq++
delete(this.freq, _freq)
}
node.freq++
if this.freq[node.freq] == nil {
this.freq[node.freq] = initDoubleLinkedList()
}
this.freq[node.freq].AddLast(node)
}
func (this *Solution) Put(key, val int) {
if this.capacity == 0 {
return
}
if node, ok := this.cache[key]; ok {
node.val = val
this.IncFreq(node)
} else {
if this.size >= this.capacity {
node := this.freq[this.minFreq].RemoveFirst()
delete(this.cache, node.key)
this.size--
}
node := &Node{
key: key,
val: val,
freq: 1,
}
this.cache[key] = node
if this.freq[1] == nil {
this.freq[1] = initDoubleLinkedList()
}
this.freq[1].AddLast(node)
this.minFreq = 1
this.size++
}
}
func LFU( operators [][]int , k int ) []int {
// write code here
res := []int{}
lfu := Constructor(k)
for _, v := range operators {
if v[0] == 1 {
lfu.Put(v[1], v[2])
} else {
res = append(res, lfu.Get(v[1]))
}
}
return res
}