2021-01-23:LFU手撸,说下时间复杂度和空间复杂度。
发布日期:2021-05-04 20:00:51 浏览次数:21 分类:原创文章

本文共 3301 字,大约阅读时间需要 11 分钟。

福哥答案2021-01-23:
这道题复杂度太高,短时间内很难写出来。面试的时候不建议手撕代码。
一个存节点的map+一个存桶的map+一个存桶的双向链表。桶本身也是一个双向链表。
存节点的map:key是键,value是节点。
存桶的map:key是次数,value是桶。
代码用golang编写,代码如下:

package mainimport (    "container/list"    "fmt")func main() {       cache := Constructor(2)    cache.Put(1, 1)    cache.Put(2, 2)    cache.Get(1)    // 返回 1    cache.Put(3, 3) // 去除键 2    cache.Get(2)    // 返回 -1(未找到)    cache.Get(3)    // 返回 3    cache.Put(4, 4) // 去除键 1    cache.Get(1)    // 返回 -1(未找到)    cache.Get(3)    // 返回 3    cache.Get(4)    // 返回 4}type LFUCache struct {       Cap int    Len int    //map缓存,键存key,值存kv和前后    KeyCache map[int]*list.Element //key存键,value存节点    List *list.List    FreqCache map[int]*list.Element //key存次数,value存桶}func Constructor(capacity int) LFUCache {       ret := LFUCache{   }    ret.Cap = capacity    ret.KeyCache = make(map[int]*list.Element)  //元素存节点    ret.FreqCache = make(map[int]*list.Element) //元素存桶    ret.List = list.New()    return ret}func (this *LFUCache) Get(key int) int {       //已经找到当前元素了    v := this.KeyCache[key]    if v == nil {           fmt.Println(-1)        return -1    }    //移动    this.curNodeMoveToNextBucket(v)    //返回当前元素的值    fmt.Println(v.Value.([]int)[1])    return v.Value.([]int)[1]}//当前节点移动到下一个桶func (this *LFUCache) curNodeMoveToNextBucket(v *list.Element) {       //根据当前节点的次数找到当前桶    curbucket := this.FreqCache[v.Value.([]int)[2]]    //找下一桶,找不到创建新桶    nextbucket := this.FreqCache[v.Value.([]int)[2]+1]    if nextbucket == nil {           nextbucket = this.List.InsertAfter(list.New(), curbucket)        this.FreqCache[v.Value.([]int)[2]+1] = nextbucket    }    //把当前节点放在下一桶里    //nextbucket.Value.(*list.List).PushBack(v.Value),这样的代码,leetcode不能通过。原因是元素移动后,已经不是以前的元素了。所以map需要重新赋值。这个错误,我花了1个小时才找到,请谨慎。    this.KeyCache[v.Value.([]int)[0]] = nextbucket.Value.(*list.List).PushBack(v.Value)    //当前桶删除当前节点    curbucket.Value.(*list.List).Remove(v)    //如果当前桶为空,直接删除当前桶。    if curbucket.Value.(*list.List).Len() == 0 {           this.List.Remove(curbucket)        delete(this.FreqCache, v.Value.([]int)[2])    }    //当前节点次数加1    v.Value.([]int)[2]++}func (this *LFUCache) Put(key int, value int) {       if this.Cap == 0 {           return    }    if v, ok := this.KeyCache[key]; ok {    //缓存里有        //修改值        v.Value.([]int)[1] = value        //移动        this.curNodeMoveToNextBucket(v)    } else {    //缓存里没有        if this.Len == this.Cap {               //获取可能需要删除的桶            deleteBucket := this.List.Front()            //获取需要删除的元素            deleteE := deleteBucket.Value.(*list.List).Front()            //删除元素            delete(this.KeyCache, deleteE.Value.([]int)[0])            deleteBucket.Value.(*list.List).Remove(deleteE)            //可能需要删除的桶如果没有元素,删除桶。并且需要删除的元素的次数不是1            if deleteBucket.Value.(*list.List).Len() == 0 {                   this.List.Remove(deleteBucket)                delete(this.FreqCache, deleteE.Value.([]int)[2])            }        } else {               this.Len++        }        //获取次数为1的桶        oneTimeBucket := this.FreqCache[1]        //获取不到就创建桶        if oneTimeBucket == nil {               oneTimeBucket = this.List.PushFront(list.New())            this.FreqCache[1] = oneTimeBucket        }        this.KeyCache[key] = oneTimeBucket.Value.(*list.List).PushBack([]int{   key, value, 1})    }}

执行结果如下:
在这里插入图片描述


上一篇:2021-01-24:手写代码:快速排序。
下一篇:2021-01-22:java中,HashMap的写流程是什么?

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2025年03月19日 07时13分42秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

SecureCRT注册机 2019-03-04
供应商解决了mini-LED的生产问题 新款MBP蓄势待发? 2019-03-04
new对象实际是在干嘛,懂了后String相关面试题随便推导 2019-03-04
Spring中@EnableCaching如何集成redis 2019-03-04
爱了!Alibaba技术官甩出的SpringCloud笔记,GitHub已标星81.6k 2019-03-04
菜鸟程序员,被无良HR欺骗,因祸得福,竟“意外”拿下美团offer 2019-03-04
已跪,Java全能笔记爆火,分布式/开源框架/微服务/性能调优全有 2019-03-04
吓我一跳?看了线程和线程池的对比,才知道池化技术到底有多牛 2019-03-04
给公司妹子讲了好久,头都大了,一个SQL语句是如何执行的? 2019-03-04
阿里大牛手撕SpringBoot,Cloud,Nginx与Docker,你凭什么搞不懂 2019-03-04
结局已定,一点不慌,秋招京东三面,给了意料之中的20KOffer。 2019-03-04
Java开发5年的我偶然被几条朋友圈打击,成功点燃,别说了,不去阿里对不起自己! 2019-03-04
面试清单(Java岗):算法+Spring+中间件+设计模式+Java+JVM+数据库 2019-03-04
凭借这份pdf,安卓顺利转行Java,成功4面拿下美团offer 2019-03-04
团体程序设计天梯赛-练习集 L1-006 连续因子 (20分) 2019-03-04
编程技巧妙用 2019-03-04
团体程序设计天梯赛-练习集 L1-023 输出GPLT (20分) 2019-03-04
团体程序设计天梯赛-练习集 L2-007 家庭房产 (25分) 并查集思想+坑点分析 2019-03-04
暴打算法:王者级数据结构与LeetCode笔记,一路绿灯杀进字节Java岗 2019-03-04
团体程序设计天梯赛-练习集 L2-020 功夫传人 (25分) dfs深搜 2019-03-04