[LeetCode] 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
使用list来维持一个list双向链表。
使用map来保存链表值及链表中该值对应的迭代器。
update()函数用来调整list中的元素位置。
get()来获取list中的元素值
put()将元素放入list中。
 
class LRUCache {
public:
    LRUCache(int capacity) : capacity(capacity){
    
    }
    
    int get(int key) {
        auto it = cache.find(key);
        // key exists.
        if (it != cache.end())
        {
            return update(it->second);
        }
        // key does not exist.
        return -1;
    }
    
    void put(int key, int value) {
        auto it = cache.find(key);
        // key exists
        if (it != cache.end())
        {
            // set new value.
            it->second->second = value;
            // update to MRU element.
            update(it->second);
        }
        // key does not exist.
        else
        {
            // cache is full. evict LRU element.
            if (data.size() >= capacity)
            {
                // delete LRU element from list.
                pair<int, int> p = data.back();
                data.pop_back();
                // remove cache entry.
                cache.erase(p.first);
            }
            // add element to the front of the list.
            data.push_front({key, value});
            // add element to the cache.
            cache[key] = data.begin();
        }
    }
private:
    // updates the position of an element to the front of the list.
    // by removing the old position from the list and updating the cache.
    int update(list<pair<int, int>>::iterator& it) {
        int key = it->first;
        int value = it->second;
        data.erase(it);
        data.push_front({key, value});
        cache[key] = data.begin();
        return value;
    }
private:
    // capacity.
    int capacity;
    // cache: {key, iterator to list element}
    unordered_map<int, list<pair<int, int>>::iterator> cache;
    // data: {key, value}
    list<pair<int, int>> data;
};

/**
 * 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);
 */

 

posted @ 2018-06-19 22:06  immjc  阅读(107)  评论(0编辑  收藏  举报