
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}) }}
执行结果如下:
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.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