LeetCode 146.LRU缓存机制

刷题链接:LRU缓存机制

题目

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。

实现 LRUCache 类:

  • LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

示例
在这里插入图片描述
LRU 算法实际上是让你设计数据结构:首先要接收一个 capacity 参数作为缓存的最大容量,然后实现两个 API,一个是 put(key, val) 方法存入键值对,另一个是 get(key) 方法获取 key 对应的 val,如果 key 不存在则返回 -1。

我们要使时间复杂度为o(1),就要让插入、查询的时间复杂度都为o(1)。那么查询时间复杂度为o(1),首先想到哈希表;在数组中尾插、尾删的时间复杂度为o(1),但是在其他位置插入、删除就不是,所以我们在这里使用双链表

在这里我们使用unorder_map以及STL中的list结构共同完成。 unordered_map用来查询,list用来存储。在unordered_map中存储的是list节点的迭代器,这样一方面可以直接查询到value,一方面可以直接拿到对应节点的迭代器,可以对list中的节点直接操作;若unordered_map中存储的是<key,value>结构,那么还需要遍历list才能找到具体节点,进行操作,时间复杂度就为o(n)。下面是unordered_map存储的结构:

unorder_map<key, list<key, value>::iterator>

图解:
在这里插入图片描述list设计中,头部是最久未使用节点,尾部是最近刚使用节点。代码设计:
插入:

1.在unordered_map表中可以查询到插入的信息

  • 获取到list节点,修改value值;因为是最近刚使用的节点,将这个节点移到list尾部

2.在unordered_map表中可以查询不到插入的信息

  • 缓存不满时,直接在list尾部插入,在unordered_map表中添加信息;
  • 缓存满了,则将最久未使用(list头部节点)删除,删除unordered_map表相关信息,然后在list尾部插入,在unordered_map表中添加信息;

获取:

  • 若获取某一节点值,通过unordered_map表,找到list节点的迭代器,获取value值;因为是最近刚使用节点,将此节点移到list尾部

具体代码:

class LRUCache {
public:
    typedef list<pair<int, int>>::iterator LIST_ITER; //链表迭代器
    LRUCache(int capacity) {
        _size = 0;
        _capacity = capacity;
    }
    
    int get(int key) {
        //在map中查找是否存在key
        auto ret = _umap.find(key);
        if(ret == _umap.end()) //找不到
             return -1;
        LIST_ITER it= _umap[key];
        
        //将此节点移到list尾部
        _lst.splice(_lst.end(), _lst, it);

        return it->second;
    }
    
    void put(int key, int value) {
        //map中是否存在key
        auto ret = _umap.find(key);
        if(ret == _umap.end())
        {
            //map中没有key值
            if(_size >= _capacity)
            {
                //map表中删除头节点的相关信息
                _umap.erase(_lst.begin()->first);
                //list中头删
                _lst.pop_front();
                --_size;
            }
            //list尾插
            _lst.push_back(make_pair(key,value));
            //map表中插入
            _umap[key] = --(_lst.end());
            ++_size;
        }
        else
        {
            //map中存在key值,修改value值
            LIST_ITER it = _umap[key];
            it->second = value;

            //将此节点移到list尾部
            _lst.splice(_lst.end(), _lst, it);
        }
    }
private:
    unordered_map<int, LIST_ITER> _umap;
    list<pair<int, int>> _lst;
    int _capacity;
    int _size;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值