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
用改的queue和map实现的。queue用来存储历史,map做cache memory。
queue不能直接用是因为需要把某个节点删除再放到末尾。
put的时间复杂度是O(1)。get在维护queue需要遍历查找key对应的节点,不能达到O(1),最差是O(n)。
/**
* 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);
*/
#include <map>
using namespace std;
struct list_node{
int key;
struct list_node* next;
struct list_node* pre;
};
class LRUCache {
private:
map<int, int> cache_mem;
struct list_node *list_head;
struct list_node *list_tail;
int capacity;
int queue_size;
public:
LRUCache(int capacity) {
this->capacity = capacity;
queue_size = 0;
list_head = list_tail = NULL;
}
int get(int key) {
map<int,int>::iterator it = cache_mem.find(key);
if(it == cache_mem.end())
return -1;
struct list_node *tmp;
for(tmp = list_head;;tmp = tmp->next){
if(tmp->key == key){
if(tmp == list_tail)
break;
if(tmp == list_head){
list_head = tmp->next;
list_head->pre = NULL;
}
else{
tmp->pre->next = tmp->next;
tmp->next->pre = tmp->pre;
}
list_tail->next = tmp;
tmp->pre = list_tail;
list_tail = tmp;
break;
}
}
return it->second;
}
void put(int key, int value) {
if(get(key) != -1){
map<int,int>::iterator it = cache_mem.find(key);
it->second = value;
return;
}
cache_mem.insert(make_pair(key,value));
if(capacity == queue_size){
struct list_node *head = list_head;
int k = head->key;
cache_mem.erase(k);
list_head = head->next;
if(list_head != NULL)
list_head->pre = NULL;
delete head;
queue_size--;
}
struct list_node *tmp = new struct list_node();
tmp->key = key;
tmp->next = NULL;
tmp->pre = NULL;
if(list_head == NULL){
list_head = tmp;
list_tail = tmp;
}
else{
list_tail->next = tmp;
tmp->pre = list_tail;
list_tail = tmp;
}
queue_size++;
}
};