问题描述
Design a data structure that follows the constraints of a Least
Recently Used (LRU) cache.Implement the LRUCache class:
- LRUCache(int capacity) Initialize the LRU cache with positive size capacity.
- int get(int key) Return the value of the key if the key exists, otherwise return -1.
- void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key.
Follow up: Could you do get and put in O(1) time complexity?
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。进阶:
你是否可以在 O(1) 时间复杂度内完成这两种操作?
思路
该问题难点在于要求查找和写入操作的时间复杂度都为O(1)。
对于功能的要求分为三点:
- 可以以O(1)复杂度查找到任意值,该部分考虑使用 hashtable 实现
- 以O(1)复杂度移除缓存中最后使用的元素,该部分使用list实现
- 以O(1)复杂度进行将元素添加或移动到缓存中最前部的操作,该部分使用list实现
class LRUCache {
public:
LRUCache(int capacity) {
capacity_ = capacity;
}
int get(int key) {
const auto it = m_.find(key);
// if key does not exist
if (it == m_.cend()) return -1;
// Move this key to the front of the list
cache_.splice(cache_.begin(), cache_, it->second);
return it->second->second;
}
void put(int key, int value) {
const auto it = m_.find(key);
//key already exists
if (it != m_.cend()){
// update the value
it->second->second = value;
// Move this key to the front of the list
cache_.splice(cache_.begin(), cache_, it->second);
return;
}
// key does not exists
// reached the capacity, remove the oldest element
if (cache_.size() == capacity_){
const auto& node = cache_.back();
m_.erase(node.first);
cache_.pop_back();
}
// Insert the entry into list and update mapping.
cache_.emplace_front(key, value);
m_[key] = cache_.begin();
}
private:
int capacity_;
list<pair<int, int>> cache_;
unordered_map<int, list<pair<int, int>>::iterator> m_;
};
/**
* 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);
*/