Leetcode: LRU Cache

来源:互联网 发布:淘宝双十一活动策划 编辑:程序博客网 时间:2024/04/29 18:04

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;elsereturn -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 findif(size < capacity){//size < capacitynode* 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 >= capacityint 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;}elsereturn -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;}};