算法 设计LFU缓存结构-(双端队列+哈希)

牛客网: 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
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值