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.
分析: 关键是对Least Recently Used (LRU) cache的理解,如果用链表,遇到一个结点,将链表中出现的这个结点全删除,然后在链表末尾加上这个结点。
链表末尾表示最近访问的结点,链表头表示最久前访问的结点,如果cache满了,要删除结点,就删除链表头结点。但这样做每次都要遍历链表,所以速度特别慢,
总是提示Time Limited Exceeded!
#include<iostream> #include<map> using namespace std; struct Lnode { int key0; int value0; Lnode *next; Lnode *pre; Lnode(int key,int value):key0(key),value0(value),next(NULL),pre(NULL){} Lnode():next(NULL),pre(NULL){} }; class LRUCache{ public: int capacity; int capacityNow; Lnode *head; Lnode *h ; map<int,int> ma,mNum;//ma记录key和value,mNum记录key和出现的次数 LRUCache(int capacity) { this->capacity = capacity; this->capacityNow = 0; head = new Lnode; h = head; } void set(int key,int value) { int num; del(head,key);// if(ma.count(key)>0)//修改 { mNum.clear(); mNum[key]++; ma[key]=value; mNum[key]++; return; } if(this->capacityNow >= this->capacity)//添加 { Lnode *pTobedeleted = head->next; while(mNum.count(pTobedeleted->key0)!=0 && this->capacityNow != 1) { pTobedeleted = pTobedeleted->next; } ma.erase(pTobedeleted->key0); Lnode *p0 = pTobedeleted->next; if(p0) p0->pre = head; head->next = p0; ma[key] = value; Lnode *pnew = new Lnode(key,value); h->next = pnew; pnew->pre = h; h = pnew; mNum.clear(); mNum[key]++; } else { mNum.clear(); mNum[key]++; ma[key] = value; this->capacityNow++; Lnode *p = new Lnode(key,value); h->next = p; p->pre = h; h = p; } } int get(int key) { if(ma.count(key)>0) { del(head,key);// mNum.clear(); mNum[key]++; Lnode *pnew = new Lnode(key,ma[key]); h->next = pnew; pnew->pre = h; h = pnew; return ma[key]; } else return -1; } private: void del(Lnode *head,int key) { Lnode *p=head->next,*p1; Lnode *h1 = head; while(p) { p1 = p->next; if(p->key0 == key) { h1->next = p1; if(p1) p1->pre = h1; } h1 = p; p = h1->next; } if(h1->key0 == key) this->h = h1->pre; else this->h = h1; } };
这道题如果稍微有一点需要遍历的,就会超时,以下是Accept的方法:
#include<iostream> #include<map> using namespace std; struct Lnode { int key0; int value0; Lnode *next; Lnode *pre; Lnode(int key,int value):key0(key),value0(value),next(NULL),pre(NULL){} Lnode():next(NULL),pre(NULL){} }; class LRUCache{ public: int capacity; int capacityNow; Lnode *head; Lnode *h ; map<int,int> ma,mNum;//ma记录key和value,mNum记录key和出现的次数 LRUCache(int capacity) { this->capacity = capacity; this->capacityNow = 0; head = new Lnode; h = head; } void set(int key,int value) { if(ma.count(key)>0)//修改 { ma[key]=value; Lnode *pnew = new Lnode(key,value); h->next = pnew; pnew->pre = h; h = pnew; mNum[key]++; return; } if(this->capacityNow >= this->capacity)//添加 { Lnode *pTobedeleted = head->next; int num = mNum[pTobedeleted->key0]; while(num !=1 || ma.count(pTobedeleted->key0)==0)//在链表中找到一个存在于ma的,且最久前没用的结点 { mNum[pTobedeleted->key0]--; pTobedeleted = pTobedeleted->next; num = mNum[pTobedeleted->key0]; } mNum[pTobedeleted->key0] = 0; head->next = pTobedeleted->next; ma.erase(pTobedeleted->key0); ma[key] = value; Lnode *pnew = new Lnode(key,value); h->next = pnew; pnew->pre = h; h = pnew; mNum[key]++; } else { mNum[key]++; ma[key] = value; this->capacityNow++; Lnode *p = new Lnode(key,value); h->next = p; p->pre = h; h = p; } } int get(int key) { if(ma.count(key)>0) { mNum[key]++; Lnode *pnew = new Lnode(key,ma[key]); h->next = pnew; pnew->pre = h; h = pnew; return ma[key]; } else return -1; } };
将访问到的结点不断的添加到链表中,同时cache满需要删除结点时,将链表的头结点往后移。用一个结点出现的次数mNum判断一个链表的结点是否是需要删除的结点。