题解 | #设计LFU缓存结构#
设计LFU缓存结构
https://www.nowcoder.com/practice/93aacb4a887b46d897b00823f30bfea1
解题思路:使用双哈希表 set + map
使用map存储key和其所有的信息node,包括key值、频率、值、最近使用时间点
使用set从小到大存储node,node根据频率和时间点进行排序,频率不相等则根据频率大小进行排序,频率相等则根据时间大小进行排序,时间大的说明使用时间更近。
#include <climits>
#include <deque>
#include <unordered_map>
#include <vector>
struct Node{
int keys,vals,fres,times;
Node(int a,int b,int c,int d):keys(a),vals(b),fres(c),times(d){}
//重载<运算符,以便根据频率和使用时间点,从小到大存于set中
bool operator<(const Node & rhs) const
{
//如果频率相等,则返回时间小的,否则返回频率小的
return fres == rhs.fres? times < rhs.times : fres < rhs.fres;
}
};
class Solution {
public:
/**
* lfu design
* @param operators int整型vector<vector<>> ops
* @param k int整型 the k
* @return int整型vector
*/
int get(int key)
{
//排除异常
if(maxsize == 0)
return -1;
auto iter = m.find(key);
//如果没有这个key值,则返回-1
if(iter == m.end())
return -1;
//取出当前键值
Node temp = iter->second;
s.erase(temp);//在set中删除
temp.fres += 1;//频率+1
temp.times = ++time;//更新使用的时间点
iter->second = temp;//存回更新后的值
s.insert(temp);//存回更新后的值
return temp.vals;
}
void put(int key,int value)
{
//排除异常
if(maxsize == 0)
return;
auto iter = m.find(key);
//如果没有该键值
if(iter == m.end())
{
//如果等于最大长度,则要删除set的第一个元素,这个元素是符合题意的
if(m.size() == maxsize)
{
m.erase(s.begin()->keys);
s.erase(s.begin());
}
//存入新的结点,频率初始为1,时间为当前时间点
Node temp = Node(key,value,1,++time);
m.insert({key, temp});
s.insert(temp);
}
//如果有该键值,则更新该键值,类似get
else
{
//取出当前键值
Node temp = iter->second;
s.erase(temp);//在set中删除
temp.fres += 1;//频率+1
temp.times = ++time;//更新使用的时间点
temp.vals = value;//更新value
iter->second = temp;//存回更新后的值
s.insert(temp);//存回更新后的值
}
}
vector<int> LFU(vector<vector<int> >& operators, int k) {
// write code here
vector<int> res;
maxsize = k;
time = 0;
for(auto x: operators)
{
if(x[0] == 1)
put(x[1],x[2]);
else
res.push_back(get(x[1]));
}
return res;
}
private:
int maxsize,time;
unordered_map<int, Node> m;
set<Node> s;
};


查看14道真题和解析