Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(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.
算法思想:
LRU算法自不必多说,我这里是想自己写写实现下hashmap和双端循环队列,所以代码比较烦,如果用STL模板库就方便多了
思想就是:利用双端循环队列处理新元素的增加及快速删除,因为头结点的next指针指向的就是最早进入队列的元素,即要删除的元素,head结点的pre指针指向的是最新加入的元素;
利用hashmap能迅速找到队列中的节点,然后将该节点加入到队尾
#define MAX 10000
#define MOD 9991
struct node{
int key;
int val;
node *pre;
node *next;
node(int k,int v):key(k),val(v),pre(this),next(this){}
};
class DQueue{
node *head;
int Size;
node *Hash[MAX][20];
int len[MAX];
int _hash(int key){
return key%MOD;
}
node * search(int key){
int pos=_hash(key);
for(int i=0;i<len[pos];i++){
if(key==Hash[pos][i]->key){
node *t=Hash[pos][i];
t->pre->next=t->next;
t->next->pre=t->pre;
t->pre=head->pre;
head->pre->next=t;
t->next=head;
head->pre=t;
return t;
}
}
return NULL;
}
public:
DQueue(){
head=new node(0,0);
memset(len,0,sizeof(len));
Size=0;
}
int insert(int key,int val){
node *i=search(key);
if(i!=NULL){
i->val=val;
return 1;
}
node *t=new node(key,val);
t->next=head;
t->pre=head->pre;
head->pre->next=t;
head->pre=t;
int pos=_hash(key);
Hash[pos][len[pos]++]=t;
Size++;
return 1;
}
int delHead(){
node *p=head->next;
head->next=p->next;
p->next->pre=head;
delete[] p;
Size--;
return 1;
}
int find(int key){
node *f=search(key);
if(f!=NULL)return f->val;
return -1;
}
int size(){
return Size;
}
};
class LRUCache{
DQueue *dq;
int capa;
public:
LRUCache(int capacity){
capa=capacity;
dq=new DQueue();
}
int get(int key){
return dq->find(key);
}
void set(int key,int value){
dq->insert(key,value);
if(dq->size()>capa){
dq->delHead();
}
}
};
answer2
//时间复杂度O(logn),空间复杂度O(n)
class LRUCache{
struct CacheNode{
int key;
int val;
CacheNode(int k,int v):key(k),val(v){}
};
public:
LRUCache(int capacity) {
this->capacity=capacity;
}
int get(int key) {
if(cacheMap.find(key) == cacheMap.end())return -1;
//把当前访问结点移到表头,并更新map
cacheList.splice(cacheList.begin(),cacheList,cacheMap[key]);
cacheMap[key] = cacheList.begin();
return cacheMap[key]->val;
}
void set(int key, int value) {
if(cacheMap.find(key) == cacheMap.end()){
if(cacheList.size() == capacity){
cacheMap.erase(cacheList.back().key);
cacheList.pop_back();
}
cacheList.push_front(CacheNode(key,value));
cacheMap[key]=cacheList.begin();
}
else{
cacheMap[key]->val=value;
cacheList.splice(cacheList.begin(),cacheList,cacheMap[key]);
cacheMap[key] = cacheList.begin();
}
}
private:
list<CacheNode> cacheList;
unordered_map<int,list<CacheNode>::iterator> cacheMap;
int capacity;
};