LRU 缓存
题目链接:LRU 缓存
请你设计并实现一个满足 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) 的平均时间复杂度运行。
方法一:双向链表
class LRUCache {
private:
int capacity;
list<pair<int, int>> cache_list; // pair 里面保存的是 key 和 value
unordered_map<int, list<pair<int, int>>::iterator> key_to_iter; // key -> 链表节点迭代器
public:
LRUCache(int capacity) : capacity(capacity) {}
int get(int key) {
auto umap_iter = key_to_iter.find(key);
if (umap_iter == key_to_iter.end()) { // 没有这本书
return -1;
}
auto list_iter = umap_iter->second; // 有这本书
// 把这本书(list_iter)从书堆(cache_list)中抽出来,放到最上面(cache_list.begin())
cache_list.splice(cache_list.begin(), cache_list, list_iter);
return list_iter->second; // 返回这本书的 value
}
void put(int key, int value) {
auto umap_iter = key_to_iter.find(key);
if (umap_iter != key_to_iter.end()) { // 有这本书
auto list_iter = umap_iter->second;
list_iter->second = value; // 更新 value
// 把这本书(list_iter)从书堆(cache_list)中抽出来,放到最上面(cache_list.begin())
cache_list.splice(cache_list.begin(), cache_list, list_iter);
return;
}
// 新书,放到最上面(emplace_front)
cache_list.emplace_front(key, value);
key_to_iter[key] = cache_list.begin();
// 书太多了
if (key_to_iter.size() > capacity) {
// 去掉最后一本书
key_to_iter.erase(cache_list.back().first);
cache_list.pop_back();
}
}
};