题解 | #设计LFU缓存结构#[GO实现]

设计LFU缓存结构

https://www.nowcoder.com/practice/93aacb4a887b46d897b00823f30bfea1

参考官方解题方案的GO代码实现,使用双哈希表和双向链表。

package main

import (
	"container/list"
	//"fmt"
	"math"
)

type Node struct{
    key,val,freq int
}

type LFUContainer struct{
    capacity,size,min_freq int
    freq_mp map[int]*list.List
    mp map[int]*list.Element
}

func NewLFUContainer(c int) LFUContainer{
    return LFUContainer{
        capacity: c,
        size: 0,
        min_freq: math.MaxInt,
        freq_mp: make(map[int]*list.List),
        mp: make(map[int]*list.Element),
    }
}

func (l *LFUContainer) update(e *list.Element,key ,value int){
    //存下原节点
    node:=e.Value.(Node)
    freq:=node.freq
    //从原频率map中删除该节点
    l.freq_mp[freq].Remove(e)
    //若当前频率没有对应节点,删除
    if l.freq_mp[freq].Len()==0{
        delete(l.freq_mp, freq)
        //如果当前频率为最小,最小频率+1
        if l.min_freq==freq{
            l.min_freq++
        }
    }
    if _,ok:=l.freq_mp[freq+1];!ok{
        //更新频率的链表不存在
        l.freq_mp[freq+1]=list.New()
    }
    //更新节点值
    node.val=value
    node.freq++
    //插入链表表头
    l.freq_mp[freq+1].PushFront(node)
    //更新map
    l.mp[key]=l.freq_mp[freq+1].Front()
}

func (l *LFUContainer) deleteLFU() {
    //获取双向链表,元素,key
    linkl:=l.freq_mp[l.min_freq]
    e:=linkl.Back()
    key:=e.Value.(Node).key
    //删除链表尾部节点
    linkl.Remove(e)
    //如果链表为空,从频率map中删除
    if linkl.Len()==0{
        delete(l.freq_mp, l.min_freq)
    }
    //从map中移除key对应节点
    delete(l.mp, key)
}

func (l *LFUContainer) set(key,value int) {
    //检查key是否在l中存在
    if e,ok:=l.mp[key];ok{
        //存在,对应更新情况
        l.update(e,key,value)
        return
    }
    //插入情况
    //判断是否达到最大容量
    if l.size==l.capacity{
        //执行删除LFU操作
        l.deleteLFU()
    }else{
        l.size++
    }
    //设置最小频率
    l.min_freq=1
    node:=Node{key,value,1}
    //在频率map中插入该节点
    if _,ok:=l.freq_mp[1];!ok{
        l.freq_mp[1]=list.New()
    }
    l.freq_mp[1].PushFront(node)
    //在map中插入该节点
    l.mp[key]=l.freq_mp[1].Front()
}

func (l *LFUContainer) get(key int) int{
    res:=-1
    //查找map
    if e,ok:=l.mp[key];ok{
        //获取值
        res=e.Value.(Node).val
        //更新频率
        l.update(e, key, res)
    }
    return res
}

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * lfu design
 * @param operators int整型二维数组 ops
 * @param k int整型 the k
 * @return int整型一维数组
*/
func LFU( operators [][]int ,  k int ) []int {
    // write code here
    container:=NewLFUContainer(k)
    res:=make([]int,0)
    for _,op:=range operators{
        switch op[0]{
            case 1:
                container.set(op[1], op[2])
            case 2:
            res = append(res, container.get(op[1]))
        }
    }
    return res
}

全部评论

相关推荐

牛客771574427号:恭喜你,华杰
点赞 评论 收藏
分享
11-29 11:21
门头沟学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务