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