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.
模拟的方法:Time Limit Exceeded
struct node{
int key;
int value;
int time;
node():key(0),value(0),time(0){};
node(int k, int v):key(k),value(v),time(0){};
};
class LRUCache{
map<int, int> mp;//mp<key, index>
vector<node> lru; //= new vector<node>(100);
vector<int> v(int); //= new vector<int>(1000);
int size;
int capacity;
public:
LRUCache(int c) {
if(c < 1)return;
//vector<node> lru(c);
lru.clear();
mp.clear();
size = 0;
capacity = c;
//cout<<"capacity:"<<capacity<<endl;
}
int get(int k) {
map<int, int>::iterator it = mp.find(k);
if(it != mp.end())
return lru[(*it).second].value;
else
return -1;
}
void set(int k, int val) {
if(capacity < 1)return;
map<int, int>::iterator it = mp.find(k);
if(it != mp.end())//find
{
lru[(*it).second].value = val;
lru[(*it).second].time = 0;
for(int i = 0; i < size; i++)
if(lru[i].key != k)
lru[i].time ++;
}else{//not find
if(size < capacity){//size < capacity
node* tmp = new node(k,val);
lru.push_back(*tmp);
/*lru[size].key = k;
lru[size].value = val;
lru[size].time = 0;*/
for(int i = 0; i < size; i++)
lru[i].time++;
mp[k] = size;
size++;
}else{//size >= capacity
int mxtime = lru[0].time;
int mxtimeindex = 0;
for(int i = 0; i < size; i++){
if(lru[i].time > mxtime)
mxtimeindex = i;
lru[i].time++;
}
it = mp.find(lru[mxtimeindex].key);
mp.erase(it);
lru[mxtimeindex].key = k;
lru[mxtimeindex].value = val;
lru[mxtimeindex].time = 0;
mp[k] = mxtimeindex;
}
}
}
};
改进Accepted
使用map+双向链表,复杂度是O(logN)
链表头部的表示刚刚访问过的,链表尾部的表示很久之前访问的
每次get(key),先在map中找到这个节点,然后把这个节点放到链表头部。
每次set(key, value),现在map中找这个节点,如果有的话就把这个节点放到链表头部,如果没有就看看cache空间是否已经满了,size>=capacity,如果未满,就生成一个新的节点放到链表头部,如果满了,就生成一个新的节点放到链表头部并且删除链表尾部的一个节点。
struct node {
node* pre;
int key;
int value;
node* next;
node(int k, int v):key(k),value(v),pre(NULL),next(NULL) {};
};
class LRUCache {
map<int, node*> mp;
node* head;
node* tail;
int size;
int capacity;
public:
LRUCache(int c) {
if (c < 1)return;
head = new node(0, 0);
tail = new node(0, 0);
head->next = tail;
tail->pre = head;
mp.clear();
size = 0;
capacity = c;
}
int get(int k) {
map<int, node*>::iterator it = mp.find(k);
if (it != mp.end()) {
node* cur = (*it).second;
cur->pre->next = cur->next;
cur->next->pre = cur->pre;
putToHead(cur);
return cur->value;
} else
return -1;
}
void set(int k, int val) {
if (capacity < 1)return;
map<int, node*>::iterator it = mp.find(k);
if (it != mp.end()) {//find
node* cur = (*it).second;
cur->pre->next = cur->next;
cur->next->pre = cur->pre;
cur->value = val;
putToHead(cur);
} else {//not find
node* tmp = new node(k,val);
putToHead(tmp);
mp[k] = tmp;
if (size < capacity) {//size < capacity
size++;
} else {//size >= capacity
node* deltmp = tail->pre;
tail->pre = deltmp->pre;
deltmp->pre->next = tail;
it = mp.find(deltmp->key);
mp.erase(it);
delete deltmp;
}
}
}
void putToHead(node* cur)
{
cur->next = head->next;
cur->pre = head;
cur->next->pre = cur;
head->next = cur;
}
};
Hash+双向链表O(1):
struct node{
node* pre;
int key;
int value;
node* next;
node(int k, int v):key(k),value(v),pre(NULL),next(NULL){};
};
class LRUCache{
unordered_map<int, node*> mp;
int capacity;
int size;
node* head;
node* tail;
public:
LRUCache(int c){
if(c<0)return;
head = new node(-1,-1);
tail = new node(-1,-1);
head->next = tail;
tail->pre = head;
mp.clear();
capacity = c;
size = 0;
}
int get(int k) {
unordered_map<int, node*>::iterator it = mp.find(k);
if(it != mp.end()){
node* p = it->second;
p->pre->next = p->next;
p->next->pre = p->pre;
putToHead(p);
return p->value;
}
else
return -1;
}
void set(int k, int val) {
if(capacity < 1) return;
unordered_map<int, node*>::iterator it = mp.find(k);
if(it != mp.end()){
node* p = it->second;
p->pre->next = p->next;
p->next->pre = p->pre;
putToHead(p);
p->value = val;
}else{
node* p = new node(k, val);
putToHead(p);
mp[k] = p;
size++;
if(size>capacity){
p = tail->pre;
tail->pre = p->pre;
p->pre->next = tail;
it = mp.find(p->key);
mp.erase(it);
delete p;
}
}
}
void putToHead(node* p)
{
p->next = head->next;
p->pre = head;
head->next->pre = p;
head->next = p;
}
};