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

解题思路:缓存的实现。map<key,<value,time>>大致是这样的数据结构,即把每个键对应到一个结构体(记录值和访问时间).
本题要求存取时间均为O(1),很容易想到hash,而当存取某个已经存在的值的时候需要把该节点放在端点处,所以需要用链表来实现。
综上,用一个list来记录当前缓存中的值,而且list是按照时间访问先后次序逆序存放着,即先访问的放在list尾部,后访问的放在list首部,
这样每次put的时候先看键是否存在,已经存在的话把它放到list首部即可,否则看是否list已满,若已满则需要弹出最后的元素,否则直接放在list首部。
class LRUCache {
public:
    LRUCache(int capacity) {
        _capacity=capacity;
    }
    
    int get(int key) {
        auto it=cache.find(key);
        if(it==cache.end())return -1;
        touch(it);
        return it->second.first;
    }
    
    void put(int key, int value) {
        auto it=cache.find(key);
        if(it!=cache.end())touch(it);
        else {
            if(used.size()==_capacity){
                cache.erase(used.back());
                used.pop_back();
            }
            used.emplace_front(key);
        }
        cache[key]={value, used.begin()};
    }
private:
    typedef list<int> LI;
    typedef pair<int, LI::iterator> PII;
    typedef unordered_map<int, PII>HIPII;
    
    int _capacity;
    HIPII cache;
    LI used;
    
    void touch(HIPII::iterator it){
        int key=it->first;
        used.erase(it->second.second);
        used.emplace_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);
 */

 

posted @ 2017-04-14 15:53  Tsunami_lj  阅读(159)  评论(0编辑  收藏  举报