题目描述
请你设计并实现一个满足LRU (最近最少使用)缓存约束的数据结构。
实现 LRUCache 类:
1 LRUCache(int capacity)
以正整数作为容量capacity
初始化LRU缓存
2 int get(int key)
如果关键字key
存在于缓存中,则返回关键字的值,否则返回 -1 。
3 void put(int key, int value)
如果关键字key已经存在,则变更其数据值value
;如果不存在,则向缓存中插入该组key-value
。如果插入操作导致关键字数量超过capacity ,则应该逐出最久未使用的关键字。
函数get
和put
必须以O(1)
的平均时间复杂度运行。
样例
输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]
解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
算法1
手写双向链表,有点麻烦,而且要注意内存泄漏
C++ 代码
struct DList{
int key;
int value;
DList* prev;
DList* next;
DList(): key(0), value(0), prev(nullptr), next(nullptr) {}
DList(int k, int v): key(k), value(v), prev(nullptr), next(nullptr) {}
};
class LRUCache {
private:
DList* head, *tail;
unordered_map<int,DList*> cache;
int C;
void remove(DList* node){
node->prev->next = node->next;
node->next->prev = node->prev;
node->prev = nullptr;
node->next = nullptr;
}
void insert(DList* node, DList* v){ // 在node之前插入v
v->prev = node->prev;
v->prev->next = v;
node->prev = v;
v->next = node;
}
public:
LRUCache(int capacity) {
C = capacity;
head = new DList(-1,-1);
tail = new DList(-1,-1);
head->next = tail;
tail->prev = head;
}
~LRUCache(){
for(auto p = head; p;) {
auto q = p->next;
delete p;
p = q;
}
}
int get(int key) {
if(cache.count(key)){
DList* cur = cache[key];
remove(cur);
insert(tail, cur);
return cur->value;
}
else return -1;
}
void put(int key, int value) {
if(cache.count(key)){
auto p = cache[key];
p->value = value;
remove(p);
insert(tail, p);
return;
}
else if(cache.size() >= C){
auto p = head->next;
cache.erase(p->key);
remove(head->next);
delete p;
}
insert(tail, new DList(key,value));
cache[key] = tail->prev;
}
};
算法2
利用STL自带的双向链表
C++ 代码
class LRUCache {
public:
LRUCache(int capacity) : _capacity(capacity) {}
int get(int key) {
if (cache.count(key)) {
Dlist.splice(Dlist.begin(), Dlist, cache[key]);
return cache[key]->second;
}
return -1;
}
void put(int key, int value) {
if (cache.count(key)) {
Dlist.splice(Dlist.begin(), Dlist, cache[key]);
cache[key]->second = value;
return;
}
else if (cache.size() >= _capacity) {
cache.erase(Dlist.back().first);
Dlist.pop_back();
}
Dlist.emplace_front(key, value);
cache[key] = Dlist.begin();
}
private:
unordered_map<int, std::list<std::pair<int, int>>::iterator> cache;
std::list<std::pair<int, int>> Dlist;
int _capacity;
};