LeetCode/solutions/146. LRU Cache.md
2020-03-02 23:27:01 +08:00

60 lines
2.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [146. LRU Cache](https://leetcode.com/problems/lru-cache/)
# 思路
题目要求设计一个最近最少使用Least Recently Used, LRU缓存。要求查询和插入都是O(1)如果插入后容量超过最大容量则需要删除最近最少使用的一个即删除元素也需O(1)。
由于时间复杂度限制为O(1)所以肯定是要用hash又因为我们需要删掉一个最不常用的元素所以我们需要维护一个按照最近使用过的先后顺序的序列这个序列要能在O(1)的时间复杂度在头部进行插入和在尾部进行删除所以可以使用双向环形链表即STL中的`list`。
综上所以我们维护一个hashmap存放key到list的迭代器的映射还要维护一个存放value的`list`其中的元素是一个pair(key, value)。
* `get`在hashmap中查找对应list的迭代器如果找到则需要将该元素移动到list头部可以先删除再在头部插入或者直接使用STL中的`splice`
* `put`现在hashmap中查找如果找到了需要先删除原来的再在list头部插入最后检测是否超过最大容量若是需要删除list尾部对应元素。
注意:
* 环形双向链表`list`的用法,如`push_front`、`pop_back`等。
* `rbegin()`返回容器最后一个元素的迭代器。
* `l.splice (iterator position, list& x, iterator i)`可以将list x的元素 i 插入到容器的position位置。
# C++
``` C++
class LRUCache {
private:
int cap;
list<pair<int,int>>values; // <key, value>
unordered_map<int, list<pair<int,int>>::iterator>cache;
public:
LRUCache(int capacity): cap(capacity){ } // 列表初始化
int get(int key) {
auto cache_iter = cache.find(key);
if(cache_iter == cache.end()) return -1;
else {
auto value_iter = cache_iter -> second;
int value = value_iter -> second;
// values.splice(values.begin(), values, value_iter); // 也可以用下面三行代码
values.erase(value_iter);
values.push_front({key, value});
cache[key] = values.begin();
return value;
}
}
void put(int key, int value) {
auto cache_iter = cache.find(key);
if(cache_iter != cache.end())
values.erase(cache_iter -> second);
values.push_front({key, value});
cache[key] = values.begin();
if(values.size() > cap){
cache.erase(values.rbegin() -> first);
values.pop_back();
}
}
};
```