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
/* 链表 + hashmap
*
* 在链表头部插入新节点, 在链表尾部删除节点
* 查找: 利用hashmap 把key映射为 Node*
*
* get: 在map中查找, 不存在, 返回-1
* 存在, 则删除这个节点,并移动到链表头部
*
* put: 若key在map中存在: 删除该节点, 插入在头部
* 否则:新建节点并插入 若此时达到容量上限再删除链表尾部
*
* 频繁的用到删除这个元素的操作: 如果知道前驱的位置 很好删除, 但是不知道,解决方法:
* (1) 使用双向链表
* (2) 设删除的是cur, 交换cur, curnext的值, 然后删除curnext.
*
* 具体到链表 可以用自己实现的双向链表 也可以用stl中list(double)
* 此处用自己定义的带头结点的双向循环链表
* */
struct Node{
int value, key;
Node *next, *pre;
Node(int k, int val):key(k), value(val), next(NULL), pre(NULL){}
};
class LRUCache {
public:
int size, count;
Node *head = new Node(0, 0);// 头结点 head->next 指向第一个节点, head->pre 指向尾节点
unordered_map<int, Node*> m;
LRUCache(int capacity) {
size = capacity;
count = 0;
head->next = head;
head->pre = head;
}
int get(int key) {
if(m.count(key)==0) return -1;
// 存在, 就删除这个节点, 然后插入到头结点后面
Node *tmp = m[key];
delNode(tmp);
pushHead(tmp);
//cout<<"get and erase"<<key<<endl;
return tmp->value;
}
void put(int key, int value) {
cout<<"put "<<key<<" "<<value<<endl;
if(m.count(key)==0){// 不存在则创建新节点, 否则只需要修改值然后放在头部
if(count==size){// 当前表已经满 则删除最后一个元素
//cout<<"too long and erase "<<head->pre->key<<endl;
m.erase(head->pre->key);
delNode(head->pre);
count--;
}
count++;
Node *tmp = new Node(key, value);
pushHead(tmp);
m[key]=tmp;
}
else{
Node *tmp = m[key];
tmp->value = value;
delNode(tmp);
//cout<<"put and erase "<<tmp->key<<endl;
pushHead(tmp);
}
}
// 在双向链表中删除节点p
void delNode(Node *p){
p->pre->next = p->next;
p->next->pre = p->pre;
}
void pushHead(Node *p){// 头插法
p->next = head->next;
head->next = p;
p->next->pre = p;
p->pre = head;
}
};