题目:
运用你所掌握的数据结构,设计和实现一个LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。
当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
进阶:
你是否可以在O(1) 时间复杂度内完成这两种操作
示例:
LRUCache cache = new LRUCache( 2 缓存容量 );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得关键字 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得关键字 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
class LRUCache {
public:
LRUCache(int capacity) {
}
int get(int key) {
}
void put(int key, int value) {
}
};
- Your LRUCache object will be instantiated and called as such:
- LRUCache* obj = new LRUCache(capacity);
- int param_1 = obj->get(key);
- obj->put(key,value);
分析
核心思想:
1.由于要求O(1),所以考虑选择数据结构是unordered_map(哈希)这个可以根据key来记录更新位置,然后使用同
样O(1)的双向链表来进行插入和删除。
2.又因为需要记录list中的节点位置,并对其操作,所以我们在unordered_map中的val是list的迭代器。
3.其实我们这样理解,即最少用的在list的最下面,每次调用的放在list最上面。这样我们可以进行先删后加,
然后每次将其都通过push_front将其放在list最上面。然后更新map中其下标的记录
#include<unordered_map>
#include<list>
using namespace std;
class LRUCache {
public:
LRUCache(int capacity) {
size = capacity;
}
int get(int key) {
if (map.count(key)){
int val = map[key]->second;
lruCache.erase(map[key]);
lruCache.push_front(pair<int,int>(key, val));
map[key] = lruCache.begin();
return val;
}
return -1;
}
void put(int key, int value) {
if (map.count(key)){
lruCache.erase(map[key]);
lruCache.push_front(pair<int,int>(key, value));
map[key] = lruCache.begin();
}
else
{
lruCache.push_front(pair<int, int>(key, value));
map[key] = lruCache.begin();
if (lruCache.size() > size){
map.erase(lruCache.back().first);
lruCache.pop_back();
}
}
return;
}
private:
int size = 0;
unordered_map<int, list<pair<int, int>>::iterator> map;
list<pair<int, int>> lruCache;
};