【力扣每日一题】2023.9.24 LRU缓存

目录

题目:

示例:

分析:

代码:


题目:

示例:

分析:

这又是一道程序设计类的题目,要我们实现LRU缓存的get和put操作。

简单说一下LRU缓存是什么,在我看来就是实用主义的体现。

比如说现在需要对一些工具进行排序,如果我用了一下锤子,那么我就拿出锤子,用完之后我就把这个锤子放在了所有工具的最前面。

如果我用了一下锄头,但是工具里没有锄头,那么我从别的地方搞来锄头之后我就放在所有工具的最前面,如果工具数量超过最大限制了,那么就把最尾巴的工具扔掉。

也就是我最近使用的就排在前面,很久不用的就排在后面,直到超过容量,把最久不用的移出缓存。

get操作就需要我们找出缓存中是否有目标的键值对,如果有,那么我们需要将这个键值对移到缓存的最开头。如果没有,那么我们直接返回-1。

put操作也需要我们找出缓存中是否有目标的键值对,如果有,那么我们更新这个键的值并且移动到缓存的最开头。如果没有,我们就添加这个键值对到缓存的开头,并且如果缓存的大小超过了限制大小,我们就把缓存的最末尾给丢掉。

这个模拟起来其实不难,难点在于常规模拟会超时,因为题目要求我们使用O(1)的平均时间复杂度,也就是我们无法遍历缓存来实现模拟操作。

我们还需要记录缓存中的先后顺序,并且有时需要改变先后顺序,因此我们应该使用链表来记录缓存。

如果我们要从容器中找出一个元素但是不能通过遍历的方式去,那么比较容易想到的就是set或是map。

所以我们本题中选择链表(list)和map来做本题,通过链表来记录LRU缓存中数据的先后顺序,使用map来查找目标键来定位到链表中对应的键值对。

使用map来将键以及对应键值对在链表中的迭代器指针进行绑定,这样即可以定位到缓存中的目标,使用迭代器也方便删除链表中的节点。

在get中,如果找不到对应键就返回-1,反之就把对应的键值对从链表中删除,再添加回链表开头,并且需要更新map中的记录。

在put中,无论找不找得到键,我们都需要把新的键值对添加到链表的开头。如果找得到键,那么我们直接把键在链表中的老地方给移除。如果找不到,我们就需要判断一下缓存的大小,如果超过大小限制,我们就需要把链表的尾部给移除。

代码:

cpp 复制代码
class LRUCache {
public:
    //存放键值
    list<pair<int,int>>l;
    //存放键所在地方的迭代器
    unordered_map<int,list<pair<int,int>>::iterator>m;
    //缓存大小
    int cap;

    LRUCache(int capacity):cap(capacity){ }
    
    int get(int key) {
        if(m.find(key)==m.end()) return -1;
        auto target=*m[key];        //获取目标的键值对
        l.erase(m[key]);            //在链表中删除目标
        l.push_front(target);       //在开头重新添加回去

        //错误示范
        // auto target=m[key];      //获取目标的迭代器
        // l.erase(target);         //这边删除之后,迭代器所指位置不变,所指元素发生改变
        // l.push_front(*target);   //添加回去的是未知元素

        m[key]=l.begin();           //修改目标值在map中的迭代器
        return target.second;
    }

    void put(int key, int value) {
        if(m.find(key)!=m.end()){   //如果缓存中有键值,删除
            l.erase(m[key]);
        }else{
            if(cap==l.size()){      //如果缓存中没有,如果容器大小封顶了,那么删除末尾
                m.erase(l.back().first);
                l.pop_back();
            }
        }
        //将新键值对添加回队列开头,并且更新map
        l.push_front(make_pair(key,value));
        m[key]=l.begin();
    }
};
相关推荐
暖焰核心16 分钟前
二叉搜索树——从插入查到key-value改写
c++
草莓熊Lotso4 小时前
【C++ 基于微服务的即时通讯系统】etcd + brpc 从安装到服务注册发现全链路实战
网络·数据库·c++·redis·微服务·etcd
inrichtt9 小时前
第八课时:SPI总线揭秘:四线全双工通信的奥
c语言·数据结构·stm32·单片机·嵌入式硬件
HPtiger10 小时前
数据结构——选择排序
数据结构·算法·排序算法
康实训10 小时前
老年评估仿真实训平台架构设计与老年人能力评估实训室教学落地实践
大数据·人工智能·算法·实训室·实训室建设
DongQiShanRen10 小时前
六根硬件映射(四):归属澄清、两处不一致与卷十一总表
开发语言·人工智能·算法·rust·哈希算法·集成学习
CCblandy10 小时前
雪花 ID 四个边界实测:时钟回拨重号 500 个,前端 JSON.parse 直接丢精度
后端·python·算法·性能优化·架构
丑梨数据10 小时前
信创环境里跑文档工具:格式兼容与本地合规的几个坑
数据结构·人工智能·算法·决策树·排序算法
烂蜻蜓10 小时前
Pandas入门教程(四):Series数据结构——创建、索引与常用方法
数据结构·pandas
把我格子衫拿来10 小时前
VTK 9.5 与 Qt 6 联合开发:从嵌入三维窗口到可维护的桌面架构
c++·python·qt·vtk·三维可视化