1、题目描述
设计一个LFU的缓存机制。实现get和put函数。
2、思路
用map m记录cache中每个键值对。
用map rec记录每个键被访问的时间戳。
用map fre记录每个键被访问的次数。
get函数:如果在m中能找到key,则返回,且更新时间戳和频率;若找不到,则返回-1.
普通函数:如果m中能找到key,则更新key对应值,以及时间戳和频率;
如果找不到,若cache没满,则直接插入键值对,和对应的时间戳对和频率。
如果cache满了,则找到频率最小的那个key,把它在m、fre、rec中的记录删除,
再插入新的键值对,时间戳对、频率。
3、代码
class LFUCache {
public:
map<int,int>m;
map<int,int>fre;
map<int,int>rec;
int t;
int n;
int c;
LFUCache(int capacity) {
t=0;
n=0;
c=capacity;
}
int get(int key) {
t++;
if(c==0) return -1;
if(m.find(key)==m.end())
return -1;
else{
rec[key]=t;
fre[key]++;
return m[key];
}
}
void put(int key, int value) {
if(c==0) return ;
t++;
if(n>0&&m.find(key)!=m.end()){
m[key]=value;
fre[key]++;
rec[key]=t;
}
else{
if(n<c){
n++;
m[key]=value;
fre[key]++;
rec[key]=t;
}
else{
map<int,int>::iterator it = fre.begin();
int k = -1,fremin = INT_MAX;
for(;it!=fre.end();it++){
if(it->second < fremin){
k = it->first;
fremin = it->second;
}
else if(it->second == fremin && rec[it->first] < rec[k]){
k = it->first;
}
}
it = m.find(k);
m.erase(it);
it = fre.find(k);
fre.erase(it);
it = rec.find(k);
rec.erase(it);
m[key]=value;
fre[key]++;
rec[key]=t;
}
}
}
};
java
public class LFUCache {
HashMap<Integer, Integer> vals;
HashMap<Integer, Integer> counts;
HashMap<Integer, LinkedHashSet<Integer>> lists;
int cap;
int min = -1;
public LFUCache(int capacity) {
cap = capacity;
vals = new HashMap<>();
counts = new HashMap<>();
lists = new HashMap<>();
lists.put(1, new LinkedHashSet<>());
}
public int get(int key) {
if(!vals.containsKey(key))
return -1;
int count = counts.get(key);
counts.put(key, count+1);
lists.get(count).remove(key);
if(count==min && lists.get(count).size()==0)
min++;
if(!lists.containsKey(count+1))
lists.put(count+1, new LinkedHashSet<>());
lists.get(count+1).add(key);
return vals.get(key);
}
public void set(int key, int value) {
if(cap<=0)
return;
if(vals.containsKey(key)) {
vals.put(key, value);
get(key);
return;
}
if(vals.size() >= cap) {
int evit = lists.get(min).iterator().next();
lists.get(min).remove(evit);
vals.remove(evit);
}
vals.put(key, value);
counts.put(key, 1);
min = 1;
lists.get(1).add(key);
}
}