LeetCode460 LFU缓存 双哈希Map
LFU缓存结构设计
http://www.nowcoder.com/questionTerminal/93aacb4a887b46d897b00823f30bfea1
搬运LeetCode460 LFU缓存
https://leetcode-cn.com/problems/lfu-cache/solution/lfuhuan-cun-by-leetcode-solution/
解法:两个哈希Map
- freq_tab:访问次数->节点链表
- key_tab:Key->节点指针
#include <unordered_map> struct Node { int key, val, freq; Node(int _key, int _val, int _freq): key(_key), val(_val), freq(_freq){} }; class Solution { private: unordered_map<int, list<Node>> freq_tab; unordered_map<int, list<Node>::iterator> key_tab; int min_freq, capacity; public: /** * 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 // 采用双哈希方法 if (k <= 0) return {}; if (operators.size() == 0) return {}; // 初始化参数 this->min_freq = 0; this->capacity = k; // 逐个执行操作 vector<int> ans; for (auto& op : operators) { if (op[0] == 1) { set(op[1], op[2]); } else { ans.push_back(get(op[1])); } } return ans; } void set(int key, int val) { // 检查是否在缓存中 if (this->key_tab.count(key)) { // 从freq_tab原位置中删除 list<Node>::iterator it = key_tab[key]; int freq_ = it->freq; freq_tab[freq_].erase(it); if (freq_tab[freq_].size() == 0) { freq_tab.erase(freq_); if (freq_ == this->min_freq) ++this->min_freq; } // 新建节点更新value和访问次数 freq_tab[freq_+1].push_front(Node(key, val, freq_+1)); key_tab[key] = freq_tab[freq_+1].begin(); } else { // 检查缓存是否满 if (this->key_tab.size() == this->capacity) { // 删除当前访问次数最少,且最久远的节点 auto& it = freq_tab[this->min_freq].back(); key_tab.erase(it.key); freq_tab[this->min_freq].pop_back(); // 如果删空了,且当前最少访问次数不是1,则从tab中去除 if (freq_tab[this->min_freq].size() == 0 && this->min_freq != 1) { freq_tab.erase(this->min_freq); } } // 更新最小访问次数 this->min_freq = 1; // 插入新节点 freq_tab[1].push_front(Node(key, val, 1)); key_tab[key] = freq_tab[1].begin(); } } int get(int key) { // 检查是否在缓存 int ret = -1; if (this->key_tab.count(key)) { ret = this->key_tab[key]->val; // 更新访问次数 int freq_ = this->key_tab[key]->freq; freq_tab[freq_].erase(this->key_tab[key]); if (freq_tab[freq_].size() == 0) { freq_tab.erase(freq_); if (freq_ == this->min_freq) ++this->min_freq; } // 新建节点更新value和访问次数 freq_tab[freq_+1].push_front(Node(key, ret, freq_+1)); key_tab[key] = freq_tab[freq_+1].begin(); } return ret; } };