刷题遇到这个,参考了别人的思路,将不同使用频率的节点放在不同的链表,用一个int记录最低出现频率,使用一个ordered_map记录节点在链表中的位置,在需要淘汰节点时可以以O1的复杂度删除节点,
实现如下:
将key,value,freq封装成结构体,节点保存在堆上,ordered_map只保存指针,淘汰节点后释放内存,
struct Node{
int key;
int value;
int freq;
Node(int a,int b,int c)
:key(a),value(b),freq(c){}
};
class LFUCache {
private:
int vol;
int minfreq;
unordered_map<int,Node*> uma;//int means key
unordered_map<int,list<Node*>> freq_map;//int means freq
unordered_map<int,list<Node*>::iterator> freq_itor;//int means key
public:
LFUCache(int capacity)
:vol(capacity),minfreq(1) {}
~LFUCache() {
for(auto ele:uma)
delete(ele.second);
}
void updateFreq(int curfreq,list<Node*>::iterator itor,Node* ptr)//更新使用频率
{
freq_map[curfreq].erase(itor);
freq_map[curfreq+1].push_front(ptr);
freq_itor[ptr->key] = freq_map[curfreq+1].begin();
}
int get(int key) {
auto itor = uma.find(key);
if(itor != uma.end())
{
Node* ptr = uma[key];
int curfreq = ptr->freq++;
auto ano_itor = freq_itor[key];
updateFreq(curfreq,ano_itor,ptr);
if(freq_map[minfreq].empty())
minfreq++;
return ptr->value;
}
else
return -1;
}
void put(int key, int value) {
auto itor = uma.find(key);
if(itor != uma.end())// find key
{
Node* ptr = uma[key];
ptr->value = value;
auto ano_itor = freq_itor[key];
int curfreq = ptr->freq++;
updateFreq(curfreq,ano_itor,ptr);
if(freq_map[minfreq].empty())
minfreq++;
}
else if(vol != 0)//not find key
{
if(uma.size() == vol)
{
Node* last = freq_map[minfreq].back();
freq_map[last->freq].pop_back();
uma.erase(last->key);
freq_itor.erase(last->key);
delete(last);//释放内存
}
Node* ptr = new Node(key,value,1);
uma[key] = ptr;
freq_map[1].push_front(ptr);
freq_itor[key] = freq_map[1].begin();
minfreq = 1;
}
}
};