LRU缓存
题解思路:O(1) map + DLinkNode(双端队列) map<int, DLinkNode *> map;
get(int key):如果key存在,返回val,并move节点到队头;否则,返回-1
void put(int key, int value): 如果key存在,更新map中val,并move节点到对头;
如果key不存在,插入节点Node到队头,插入map,size++;判断size 是否超过阈值,如果超过,删除队尾元素
146 LRU
实现
LRUCache类:
LRUCache(int capacity)以 正整数 作为容量capacity初始化 LRU 缓存int get(int key)如果关键字key存在于缓存中,则返回关键字的值,否则返回-1。void put(int key, int value)如果关键字key已经存在,则变更其数据值value;如果不存在,则向缓存中插入该组key-value。如果插入操作导致关键字数量超过capacity,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
// 双向链表
struct DLinkNode {
int key, val;
DLinkNode *pre;
DLinkNode *next;
DLinkNode() : key(0), val(0), pre{nullptr}, next{nullptr} {};
DLinkNode(int _key, int _val) : key(_key), val(_val), pre{nullptr}, next{nullptr} {}
};
class LRUCache {
private:
map<int, DLinkNode *> map;
DLinkNode *head;
DLinkNode *tail;
int size;
int capacity;
public:
LRUCache(int capacity) {
this->capacity = capacity;
size = 0;
head = new DLinkNode();
tail = new DLinkNode();
head->next = tail;
tail->pre = head;
}
void addToHead(DLinkNode *p) {
DLinkNode *q = head->next;
p->pre = head;
p->next = q;
q->pre = p;
head->next = p;
}
void removeNode(DLinkNode *p) {
p->pre->next = p->next;
p->next->pre = p->pre;
}
void moveToHead(DLinkNode *p) {
removeNode(p);
addToHead(p);
}
DLinkNode *removeTail() {
DLinkNode *removed = tail->pre;
removeNode(removed);
return removed;
}
int get(int key) {
int res = -1;
if (map.count(key)) {
res = map[key]->val;
DLinkNode *p = map[key];
moveToHead(p);
}
return res;
}
void put(int key, int value) {
if (map.count(key)) { //缓存已存在key,更新val并且移动node到链表头部
DLinkNode *p = map[key];
p->val = value;
moveToHead(p);
} else { //缓存不存在key,新node插入到链表头部,hashmap中插入新node key
DLinkNode *p = new DLinkNode(key, value);
map[key] = p;
size++;
addToHead(p);
if (size > capacity) { //超过链表容量,移除链表尾部指针
auto removed = removeTail();
map.erase(removed->key);
delete removed;
size--;
}
}
}
};