设计/map-困难-leetcode. LRU缓存机制

题目来源:LRU缓存机制

不知道LRU的同学可以看看操作系统关于页面置换规则的部分或直接百度百科。这里我就不搬砖了。

这道题要实现的话,我认为难度其实算中等。主要难度在于如何实现O(1)时间复杂度。由于存在key->value,因此我们必定需要一个map和一个list,map存储key对应的指针(或指向列表中迭代器),list存储实际的(key,value)单元。可能有同学有疑问,map为什么不直接存value,list为什么存了value还要存key。实际上,如果只是单纯的put和get操作,我们使用一个map存储key->value即可,但是由于我们需要实现LRU的机制。因此,必须有一个list,list中元素的位置表示元素的优先级,每个元素被访问时,我们就将该元素提至list首部,当存储空间满时,list尾部的元素必然要删除,同时map中的位置也要删除,因此,list必然要有元素在map中对应的位置key。同时,每次get之后,都要删除list中元素的位置,同时重新在list首部插入该元素,为了便于查找元素在list中的位置。因此,map中不直接存储value,而是存储list中国年对应元素为first的迭代器。

需要注意的是,C++中,map的查找时间复杂度不是常数,是对数函数,因为其底层实现是红黑树。hash_map和unordered_map才是常数复杂度,但是内存利用率不高,因为底层有很多桶(详情自行百度hash map算法),数据少的时候都是闲置的。在微软的文档中,hash_map不推荐使用,用unordered_map替代(不知道为什么,但是用起来感觉是一样的,接口都没变)。

还有一点也是要注意的,C++中list::size()是O(n)的复杂度计算list长度,效率太低,建议直接自己定义变量存储listsize,并实时更新

最后上代码

class LRUCache {
private:
    int cache_capacity = 0;
    int used = 0;
    list<pair<int, int>> cache;  // 第一个是元素在map中的key 第二个是value
    unordered_map<int, list<pair<int, int>>::iterator> key_cache_map;      // 映射key与元素在list中的位置
public:
    LRUCache() {
        cache_capacity = 0;
    }

    LRUCache(int capacity) {
        cache_capacity = capacity;
    }
    
    int get(int key) {
        auto result = key_cache_map.find(key);
        if (key_cache_map.end() == result) {
            return -1;
        }

        // 每次get将元素重新提至list首部的过程
        // 可以视作将元素删除后再次执行put的过程
        put(key, key_cache_map[key]->second);

        return key_cache_map[key]->second;
    }

    void put(int key, int value) {
        auto find = key_cache_map.find(key);
        if (find != key_cache_map.end()) {
            // 如果key已存在则移除元素
            cache.erase(find->second);
            key_cache_map.erase(find);
            used--;
        } else if (cache_capacity <= used) {
            cout << "full rm " << cache.back().first << endl;
            // 空间已满 移除末尾元素
            key_cache_map.erase(cache.back().first);
            cache.pop_back();
            used--;
        }

        // 插入元素至list头部并更新map
        pair<int, int> p = make_pair(key, value);
        cache.push_front(p);
        key_cache_map[key] = cache.begin();
        used++;
    }
};

提交结果如下
在这里插入图片描述

用stl的LinkedHashMap也能很容易实现不过那样难度就更低了,我就不搬砖了,有兴趣的可以百度~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值