leetcode 146. LRU Cache

来源:互联网 发布:.top域名为什么便宜 编辑:程序博客网 时间:2024/06/07 06:25

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 1cache.put(3, 3);    // evicts key 2cache.get(2);       // returns -1 (not found)cache.put(4, 4);    // evicts key 1cache.get(1);       // returns -1 (not found)cache.get(3);       // returns 3cache.get(4);       // returns 4
get操作时,需要执行下面两步操作:
1/返回map中key对应的value;
2/同时需要更新list中key的位置,将key放置在list中最近被访问的位置上,那么可以定义list中的首端(front)元素是最近被访问的元素。更新操作同样需要两部来完成:1:删除list中原来的key;2:将key插入list首端。

set操作会比较复杂一些:
1/首先判断要插入的key是否存在map中,如果存在的话,只需要更新map中对应的value,同时执行上面get中的第二步操作;
2/如果key不存在map中,那么需要判断map容量是否已满,如果满了,就需要从map中删除一个元素,这时list就派上用场了,因为最近使用的key位于list的首端,那么最久未使用的元素就位于list尾端,可以从list中取出最久未使用的key,同时删除map中对应的key和value。
3/然后将数据插入map和list中。

注意要点:
1、pair的用法   typedef pair<int, list<int>::iterator> PILI;
2、typedef的用法
3、iterator的用法。只要把一个元素的it存下来,之后就能用这个定位。和数组前面插入,后面的后移是不一样的。
4、map最后一个元素 s.back()
5、list是插入删除最快的STL,特点是可以两端插入删除。


class LRUCache {public:    LRUCache(int capacity)     {        this->capacity = capacity;    }        int get(int key)     {        auto it = datas.find(key);        if( it != datas.end() )        {            update(it);            return it->second.first;        }        else            return -1;    }        void put(int key, int value)     {        int length = datas.size();          auto iter = datas.find(key);          if (iter != datas.end())  //如果找到了        {              iter->second.first = value;              update(iter);          }          else          {              if(length >= capacity)              {                  datas.erase(s.back());      //把最后面那个key对应的map删除                s.pop_back();               //把list中的最后那个key删除            }              s.push_front(key);              datas[key] = PILI(value, s.begin()); //关键!          }    }    private:    typedef pair<int, list<int>::iterator> PILI;  //第一位存 value,第二位 存 在list中的位置(迭代器)    map<int, PILI> datas; //存数据    int capacity;    list<int> s;  //list存的是key值,但关键是迭代器的位置。 s.front()是最近的。  list的特点就是中间删除很快        void update(map<int, PILI>::iterator it)  //更新map的这个迭代器    {        int key = it->first;           s.erase(it->second.second);     //删除原本的位置        s.push_front(key);              //移动到最前面去        it->second.second = s.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); */