leetcode刷题-146. LRU缓存机制

146. LRU缓存机制

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put

获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1
写入数据 put(key, value) - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lru-cache
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

一、什么是 LRU 算法 by labuladong

就是一种缓存淘汰策略。

计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾位置。但问题是,删除哪些内容呢?我们肯定希望删掉哪些没什么用的缓存,而把有用的数据继续留在缓存里,方便之后继续使用。那么,什么样的数据,我们判定为「有用的」的数据呢?

LRU 缓存淘汰算法就是一种常用策略。LRU 的全称是 Least Recently Used,也就是说我们认为最近使用过的数据应该是是「有用的」,很久都没用过的数据应该是无用的,内存满了就优先删那些很久没用过的数据。

思路:

缓存机制,首先得有一个缓存容量 capacity
然后在get()put()更新时需要查找,(key/value)类型多使用Hash表,时间复杂度O(1)。因为缓存机制的问题,需要对缓存区增删改,还要有顺序,链表有顺序,单向链表不支持前驱,增删慢,双向链表快。所以使用哈希表+双向链表

首先构建哈希表与双向链表的链接。哈希表键区存储链表中存在的值,方便查找,值区存储对应键的地址。unordered_map>::iterator> map
双向链表: 以对应的元组构成,

代码

class LRUCache {
private:
    int cap;//容量大小
    list<pair<int,int>> cache;//双向链表
    unordered_map<int,list<pair<int,int>>::iterator> map;//哈希表,键与双向链表对应链接
public:
    LRUCache(int capacity) {
        this->cap = capacity;
    }
    
    int get(int key) {
        auto it = map.find(key);
        //访问的key不存在
        if(it == map.end()) return -1;
        //key存在,把 (k, v) 换到队头
        pair<int,int> kv = *map[key];
        //删除哈希表中原来的地址
        cache.erase(map[key]);
        //把 (k, v) 换到队头
        cache.push_front(kv);
        //更新 (key, value) 在 cache 中的位置
        map[key] = cache.begin();
        return kv.second;//返回value
    }
    
    void put(int key, int value) {
        //判断key是否存在
        auto it = map.find(key);
        if (it == map.end()){
            /* key 不存在,判断 cache 是否已满 */ 
            if (cache.size() == cap){
                // cache 已满,删除尾部的键值对腾位置
                // cache 和 map 中的数据都要删除
                auto lastPair = cache.back();
                int lastKey = lastPair.first;
                map.erase(lastKey);
                cache.pop_back();
            }
            //cache 没满,可以直接添加
            cache.push_front(make_pair(key,value));
            map[key] = cache.begin();
        }else{
            /* key 存在,更改 value 并换到队头 */
            cache.erase(map[key]);
            cache.push_front(make_pair(key,value));
            map[key] = cache.begin();
        }
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

你可能感兴趣的:(leetcode刷题)