LeetCode-146:LRU Cache (最近使用缓存)

题目:

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

  • get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
  • put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

Follow up:
Could you do both operations in O(1) time complexity?

例子:

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4

问题解析:

设计一个最近使用缓存的结构,使得该缓存具有get和put操作,并且,缓存有容量(capacity)上限。

链接:

思路标签

链表hash map

解答:

  • 为快速添加和删除,我们需要使用链表来设计cache,链表中从头到尾的数据顺序依次是:(最近访问)->…(最旧访问);
  • 因为是最近访问的在链表的最前,我们使用list来保存key值,而使用hashmap来保存(key,value)对即可,同时需要对value进行改造,因为我们还需要将每一个value与list中的key结点进行绑定,组成pair,以便每次操作进行list的最近访问的调整;
  • 添加节点put(key, value):
    • 判断hashmap中是否存在key节点,如果存在则调整List,将key置为头部(最近访问),更新hashmap指向key节点的指针;
    • 如果不存在key值对,则判断capacity是否满容,若不满容量则直接在list和hashmap中加入新节点(list在表头添加);否则则删除list末尾key和hashmap中的对应值对,再进行添加。
    • 新节点插入到表头即可,时间复杂度O(1)。
  • 查找节点get(key):
    • 在hashmap中查询,若不存在则返回-1;
    • 若存在,则调整list位置更新hashmap对应指针,返回key对应的value;
    • 每次节点被查询到时,将节点移动到链表头部,时间复杂度O(1)。
class LRUCache {
public:
    LRUCache(int capacity) : _capacity(capacity) {}

    int get(int key) {
        auto it = cache.find(key);
        if(it == cache.end())
            return -1;
        adjust(it);
        return it->second.first;
    }

    void put(int key, int value) {
        auto it = cache.find(key);
        if(it != cache.end())
            adjust(it);
        else{
            if(cache.size() == _capacity){
                cache.erase(used.back());
                used.pop_back();
            }
            used.push_front(key);
        }
        cache[key] = {value, used.begin()};
    }

private:
    typedef pair<int, list<int>::iterator> valListPair;
    typedef unordered_map<int, valListPair> keyValMap;
    list<int> used;
    keyValMap cache;
    int _capacity;

    void adjust(keyValMap::iterator it){
        int key = it->first;
        used.erase(it->second.second);
        used.push_front(key);
        it->second.second = used.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);
 */

猜你喜欢

转载自blog.csdn.net/koala_tree/article/details/80326015
今日推荐