146. LRU 缓存
- 超时的思路
class Node {
public:
int val;
int key;
Node * pre, * next;
Node(int k,int v):val(v), key(k), pre(NULL), next(NULL){}
Node():pre(NULL), next(NULL){}
};
class LRUCache {
private:
// 5.bug. 类的成员变量必须初始化,因为是放在栈中的,size不初始化就是个负无穷,永远都不可能大于capcitity
int cap, size = 0;
Node * head, *p, *tail;
unordered_map<int, Node*> cache;
public:
LRUCache(int capacity) {
cap = capacity;
head = new Node();
tail = new Node();
head->next = tail;
tail->pre = head;
}
int get(int key) {
if (cache.count(key) == 0) return -1;
p = cache[key];
deleteNode(p);
addToHead(p);
//printNodeList();
// 1.bug. 在输出链表的时候把p移动了,回来又用移动之后的返回,尽量能用局部变量就用局部叭,全局的说不定哪一糊涂就给改了。
return p->val;
}
void put(int key, int value) {
Node * now = new Node(key, value);
// 4.bug. 判断hash表中是否已经存在该元素,!用反了
if (cache.count(key) != 0) {
// 2.bug. 开始为了减少冗余代码,把addToHead放到了if外面,虽然两块的addToHead都会执行,但由于先执行了它,改变了判断条件,导致进入了不同的if逻辑
// 6.bug. 开始的时候先delete在add的,add和delete里面都有对cache的操作,add之后delete就会把cache的记录一起干掉,对全局变量的操作还是拿出来比较好。
deleteNode(cache[key]);
addToHead(now);
cout<<"++++cache[key] "<<cache[key]->key<<endl;
return;
}
addToHead(now);
if (size > cap) {
deleteNode(tail->pre);
}
printNodeList();
}
void addToHead(Node * now) {
head->next->pre = now;
now->next = head->next;
head->next = now;
now->pre = head;
cache[now->key] = now;
size++;
}
void deleteNode(Node * now) {
now->pre->next = now->next;
now->next->pre = now->pre;
// 3.bug map删除一个元素用erase,肯定和数组写哈希表不能混用,不能用cache[key] = NULL,这样的话,查找的时候是能查找到元素的
cache.erase(now->key);
size--;
}
};