描述
设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能
set(key, value):将记录(key, value)插入该结构
get(key):返回key对应的value值
[要求]
set和get方法的时间复杂度为O(1)
某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。
当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。
若opt=1,接下来两个整数x, y,表示set(x, y)
若opt=2,接下来一个整数x,表示get(x),若x未出现过或已被移除,则返回-1
对于每个操作2,输出一个答案
解题思路
- 要求set和get方法的时间复杂度为O(1),首先想到的就是unordered_map
- LRU缓存结构实际上是一种有序的结构,根据访问顺序来进行排序,只要有一种结构能保存这种顺序即可,使用vector、list、链表等等都行
- 题目要求在构造时确定大小,所以要有一个成员变量表示最大缓存大小m_max_size,在类的构造函数中进行初始化
- 既然有了m_max_size就要有一个表示当前缓存大小的成员变量m_current_size,在插入的时候需要将m_current_size加1,在删除元素的时候需要将m_current_size减1,需要注意的是m_current_size不能比m_max_size大,凡是超过的情况下都应该删除元素
代码
class Solution {
public:
/**
* lru design
* @param operators int整型vector<vector<>> the ops
* @param k int整型 the k
* @return int整型vector
*/
vector<int> LRU(vector<vector<int> >& operators, int k) {
//operators = [[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]]
//oper0=[1,1,1] oper1=[1,2,2] oper2=[1,3,2] ...
//k = 3
vector<int> ret;
lru_cache cache(k);
for(auto& oper: operators)
{
if(oper[0] == 1) {
cache.set(oper[1], oper[2]);
}else if(oper[0] == 2) {
ret.push_back(cache.get(oper[1]));
}
}
return ret;
}
class lru_cache {
public:
lru_cache(int k)
{
m_max_size = k;
m_current_size = 0;
}
void set(int key, int value);
int get(int key);
private:
using lru_list = std::list<std::pair<int, int>>;
using lru_list_iter = lru_list::iterator;
using lru_map = unordered_map<int, lru_list_iter>;
using lru_map_iter = lru_map::iterator;
lru_list m_list;
lru_map m_map;
int m_max_size;
int m_current_size;
void increase_size() {
m_current_size++;
}
void decrease_size() {
m_current_size--;
}
};
};
void Solution::lru_cache::set(int key, int value)
{
lru_map_iter map_iter = m_map.find(key);
if(map_iter != m_map.end()) {
//覆盖旧的值;
map_iter->second->second = value;
//更新LRU;
m_list.splice(m_list.begin(), m_list, map_iter->second);
}else {
//插入新值到首部;
m_list.push_front(make_pair(key,value));
//更新m_map;
m_map[key] = m_list.begin();
//插入后当前大小增加;
increase_size();
lru_list_iter list_iter;
while(m_current_size > m_max_size && !m_list.empty()) {
//获取最不常用的元素并进行删除;
list_iter = --m_list.end();
m_map.erase(list_iter->first);
m_list.erase(list_iter);
//删除后当前大小减少;
decrease_size();
}
}
}
int Solution::lru_cache::get(int key)
{
lru_map_iter map_iter = m_map.find(key);
if(map_iter != m_map.end()) {
//更新LRU;
m_list.splice(m_list.begin(), m_list, map_iter->second);
//返回最终查询到的数据;
return map_iter->second->second;
}else {
//没有找到则返回-1;
return -1;
}
};拓展
集合set是无序的,cpp中如何实现一个有插入顺序的set呢,和此题类似,满足插入、查询的需求可使用unordered_map,使用vector、list、链表等保证插入顺序即可

京公网安备 11010502036488号