题目大意:
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
进阶:
你是否可以在 O(1) 时间复杂度内完成这两种操作?
解题思路:
想在O(1)时间完成,必须用双向链表来存key,val;然后我们需要用hash来快速定位到哪一个链表的节点。
class LRUCache {
public:
struct ListNode {
ListNode * next;
ListNode * prev;
int val;
int key_val;
ListNode(int v,int kv):val(v),key_val(kv),next(NULL),prev(NULL){};
};
int cap;
unordered_map<int,ListNode *> mm;
ListNode * head;
ListNode * tail;
LRUCache(int capacity) {
cap = capacity;
head= NULL;
tail = NULL;
}
int get(int key) {
if(!mm.count(key))return -1;
if(mm[key]!=head){
ListNode * tmp = mm[key]->prev;
if(mm[key] == tail && mm.size()>1)tail = tmp;
if(mm[key]->prev)mm[key]->prev->next = mm[key]->next;
if(mm[key]->next)mm[key]->next->prev = mm[key]->prev;
mm[key]->prev = NULL;
mm[key]->next = head;
if(head)head->prev = mm[key];
head = mm[key];
//cout<<"get method "<<tail->key_val<<" "<<tail->val<<endl;
}
return mm[key]->val;
}
void put(int key, int value) {
//cout<<"putting "<<key<<" "<<value<<endl;
if(!mm.count(key)){
if(mm.size() == cap){
// cout<<"tail "<<tail<<endl;
if(tail->prev)tail->prev->next = NULL;
mm.erase(tail->key_val);
tail = tail->prev;
}
ListNode * poi = new ListNode(value,key);
mm[key] = poi;
mm[key]->next = head;
if(head)head->prev = mm[key];
// if(head)cout<<"head prev "<<head->prev<<endl;
head = mm[key];
// cout<<"after inserting head "<<head<<endl;
if(!tail)tail = mm[key];
}else{
mm[key]->val = value;
if(mm[key]!=head){
ListNode * tmp = mm[key]->prev;
if(mm[key] == tail && mm.size()>1)tail = tmp;
if(mm[key]->prev)mm[key]->prev->next = mm[key]->next;
if(mm[key]->next)mm[key]->next->prev = mm[key]->prev;
mm[key]->prev = NULL;
mm[key]->next = head;
if(head)head->prev = mm[key];
head = mm[key];
if(!tail)tail = mm[key];
}
}
// cout<<"tail key val"<<tail->key_val<<" "<<tail->val<<endl;
}
};
/**
* 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);
*/