学过操作系统的应该都有了解LRU,LFU缓存结构,这里也不多说了,就是找地方记录一下代码实现
LRU题目如下
解决方案
解决方案很好想
- 灵活调整数据位置肯定是首选双向链表了
- O(1)时间找到某个value肯定是哈希表了
代码实现
//双向链表
struct Node{
int key;
int val;
Node* pre;
Node* next;
//初始化
Node(int k, int v): key(k), val(v), pre(NULL), next(NULL){};
};
class Solution {
private:
int size = 0;
unordered_map<int, Node*> map;
Node* head;
Node* tail;
public:
Solution(int capacity) {
// write code here
this->size = capacity;
this->head = new Node(0, 0);
this->tail = new Node(0, 0);
head->next = tail;
tail->pre = head;
}
void removeLast() {
map.erase(tail->pre->key);
tail->pre->pre->next = tail;
tail->pre = tail->pre->pre;
}
void insertFirst(Node* node) {
node->next = head->next;
node->pre = head;
head->next->pre = node;
head->next = node;
}
void moveToHead(Node* node) {
if(node->pre == head) return;
node->pre->next = node->next;
node->next->pre = node->pre;
insertFirst(node);
}
int get(int key) {
// write code here
if (map.find(key) == map.end()) return -1;
moveToHead(map[key]);
return map[key]->val;
}
void set(int key, int value) {
// write code here
if(map.find(key) == map.end()) {
Node* node = new Node(key, value);
map[key] = node;
if(this->size <= 0) {
removeLast();
} else {
this->size--;
}
insertFirst(node);
} else {
map[key]->val = value;
moveToHead(map[key]);
}
}
};
LFU题目如下
解题思路
- 灵活调整首尾节点还是需要双向链表
- 整个结构需要通过操作次数cnt分级,所以一个cnt要对应一个链表,这需要一个
cnt-链表
的hash表 - get操作需要通过key快速找到val,一个key对应一个节点,所以这还需要一个
key-某链表节点
的hash表
代码实现
class Solution {
public:
unordered_map<int, list<vector<int>> :: iterator>key_map;//key - 链表节点
unordered_map<int, list<vector<int>> >cnt_map;//cnt - list{cnt, key, val}
int min_cnt = 0;
int size = 0;
/**
* lfu design
* @param operators int整型vector<vector<>> ops
* @param k int整型 the k
* @return int整型vector
*/
vector<int> LFU(vector<vector<int> >& operators, int k) {
// write code here
size = k;
vector<int> res;
for(int i=0;i<operators.size();i++) {
auto &op = operators[i];
if(op[0]==1) set(op[1], op[2]);
else res.push_back(get(op[1]));
}
return res;
}
void set(int key, int val) {
auto it = key_map.find(key);
if(it != key_map.end()) update(it->second, key, val);
else {
if(size == 0) {
int min_early_key = cnt_map[min_cnt].back()[1];
cnt_map[min_cnt].pop_back();
if(cnt_map[min_cnt].empty()) cnt_map.erase(min_cnt);
key_map.erase(min_early_key);
}
else size--;
min_cnt=1;
cnt_map[1].push_front({1, key, val});
key_map[key] = cnt_map[1].begin();
}
}
void update(list<vector<int>> :: iterator it, int key, int val) {
int cnt = (*it)[0];
cnt_map[cnt].erase(it);
if(cnt_map[cnt].empty()) {
cnt_map.erase(cnt);
if(min_cnt == cnt) min_cnt++;
}
cnt_map[cnt+1].push_front({cnt+1, key, val});
key_map[key] = cnt_map[cnt+1].begin();
}
int get(int key) {
auto it = key_map.find(key);
int val = -1;
if(it != key_map.end()) {
auto list_iter = it->second;
val = (*list_iter)[2];
update(list_iter, key, val);
}
return val;
}
};