转自:http://blog.csdn.net/doc_sgl/article/details/15378513
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;
- vector<node> lru;
- vector<int> v(int);
- int size;
- int capacity;
- public:
- LRUCache(int c) {
- if(c < 1)return;
-
- lru.clear();
- mp.clear();
- size = 0;
- capacity = c;
-
- }
-
- 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())
- {
- 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{
- if(size < capacity){
- node* tmp = new node(k,val);
- lru.push_back(*tmp);
-
-
-
- for(int i = 0; i < size; i++)
- lru[i].time++;
- mp[k] = size;
- size++;
- }else{
- 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()) {
- node* cur = (*it).second;
- cur->pre->next = cur->next;
- cur->next->pre = cur->pre;
- cur->value = val;
- putToHead(cur);
- } else {
- node* tmp = new node(k,val);
- putToHead(tmp);
- mp[k] = tmp;
- if (size < capacity) {
- size++;
- } else {
- 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;
- }
- };