lru 缓存结构
题目描述:
设计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,输出一个答案
示例1
输入
[[1,1,1],[1,2,2],[1,3,2],[2,1],[1,4,4],[2,2]],3
输出
[1,-1]
说明
第一次操作后:最常使用的记录为(“1”, 1)
第二次操作后:最常使用的记录为(“2”, 2),(“1”, 1)变为最不常用的
第三次操作后:最常使用的记录为(“3”, 2),(“1”, 1)还是最不常用的
第四次操作后:最常用的记录为(“1”, 1),(“2”, 2)变为最不常用的
第五次操作后:大小超过了3,所以移除此时最不常使用的记录(“2”, 2),加入记录(“4”, 4),并且为最常使用的记录,然后(“3”, 2)变为最不常使用的记录
备注:
1 ≤ k ≤ n ≤ 1 0 5 1 \leq k \leq n \leq 10^5 1≤k≤n≤105
− 2 × 1 0 9 ≤ x , y ≤ 2 × 1 0 9 -2 \times 10^9 \leq x,y \leq 2 \times 10^9 −2×109≤x,y≤2×109
题解:
开始初始化一个head节点与一个tail节点,方便以后插入节点和删除节点,中间放置操作的节点。
-
[1,1,1] 当我们遇到第一个set方法的时候 就需要插入到head 和tail 之间,
-
[1,2,2] 这时我们需要将新节点插入到head与node(1,1)之间。
-
[1,3,2] 添加到head后面;
-
[2,1] 发现已经有key=1对应的节点;则把node(1,1)移动到head后面;
-
[1,4,4] 这时候发现节点的数量已经达到内存上限,则需要把最不常用的节点node(2,2)删除,把新节点插入到head后面;
-
[2,2] 这时候查找节点发现没有,则返回-1;
代码:
#include <unordered_map>
struct dlistnode{
int key, val;
dlistnode* pre;
dlistnode* next;
dlistnode(int k, int v): key(k), val(v), pre(nullptr), next(nullptr){ };
};
class solution {
private:
int size = 0;
dlistnode* head;
dlistnode* tail;
unordered_map<int, dlistnode*> mp;
public:
/** * lru design * @param operators int整型vector> the ops * @param k int整型 the k * @return int整型vector */
vector<int> lru(vector<vector<int> >& operators, int k) {
// write code here
if(k < 1) return { };
this->size = k;
this->head = new dlistnode(0,0);
this->tail = new dlistnode(0,0);
this->head->next = this->tail;
this->tail->pre = this->head;
if(operators.size() == 0) return { };
vector<int> res;
for(vector<int> op : operators){
if(op[0] == 1) {
set(op[1], op[2]);
}
else if(op[0] == 2){
int value = get(op[1]);
res.push_back(value);
}
}
return res;
}
void set(int key, int val){
if(mp.find(key) == mp.end()){ // hashmap 中没找到
dlistnode* node = new dlistnode(key, val);
mp[key] = node;
if(this->size <= 0){
removelast();
}
else{
this->size--;
}
insertfirst(node);
}
else{ // hashmap 中已经有了,也就是链表里也已经有了
mp[key]->val = val;
movetohead(mp[key]);
}
}
int get(int key){
int ret = -1;
if(mp.find(key) != mp.end()){
ret = mp[key]->val;
movetohead(mp[key]);
}
return ret;
}
void movetohead(dlistnode* node){
if(node->pre == this->head) return;
node->pre->next = node->next;
node->next->pre = node->pre;
insertfirst(node);
}
void removelast(){
mp.erase(this->tail->pre->key);
this->tail->pre->pre->next = this->tail; // remove the last node in dlist
this->tail->pre = this->tail->pre->pre;
}
void insertfirst(dlistnode* node){
node->pre = this->head;
node->next = this->head->next;
this->head->next->pre = node;
this->head->next = node;
}
};