请你设计并实现一个满足 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) 的平均时间复杂度运行。
示例
1. 方法一:哈希+queue
使用一个队列记录所有操作,并在哈希表中记录对数据的操作次数,在存入数据时按照队列遍历,第一个操作次数为1的数据应该被清除
class LRUCache {
public:
LRUCache(int capacity)
:msize(capacity)
{}
int get(int key) {
if(m.find(key) != m.end()){
que.push(key);
m[key].first++;
return m[key].second;
}
return -1;
}
void put(int key, int value) {
m[key].second = value;
m[key].first++;
que.push(key);
if(m.size() > msize){
while(m[que.front()].first > 1){
m[que.front()].first--;
que.pop();
}
m.erase(que.front());
que.pop();
}
}
private:
int msize;
queue<int> que;
unordered_map<int, pair<int, int>> m;
};
2. 方法二:哈希+list
class LRUCache {
public:
LRUCache(int capacity)
:msize(capacity){}
int get(int key){
auto it = m.find(key);
if(it != m.end()){
//将lr中it->second元素剪贴到lr.begin()位置
lr.splice(lr.begin(), lr, it->second);
return it->second->second;
}
return -1;
}
void put(int key, int value){
auto it = m.find(key);
if(it != m.end()){
lr.splice(lr.begin(), lr, it->second);
it->second->second = value;
return;
}
lr.emplace_front(key, value);
m[key] = lr.begin();
if(m.size() > msize){
m.erase(lr.back().first);
lr.pop_back();
}
}
private:
int msize;
std::list<pair<int, int>> lr;
unordered_map<int, std::list<std::pair<int, int>>::iterator> m;
};