LFU算法

思路

LFU每个freq对应的集合其实就是个LRU,淘汰K时,会首先选取freq最小的集合,其次选取最久未使用的Key。
更新或者查询时,会将对应的K/V从当前freq提升至freq+1集合的末尾(假如头代表最久未使用)。

插入

image

查询

image

代码实现

···
class LFUCache {

private int minFreq;
private int capacity;
private Map<Integer, Integer> keyToVal;
private Map<Integer, Integer> keyToFreq;
private Map<Integer, LinkedHashSet<Integer>> freqToKeys;
public LFUCache(int capacity) {
this.capacity = capacity;
this.minFreq = 0;
keyToVal = new HashMap<>();
keyToFreq = new HashMap<>();
freqToKeys = new HashMap<>();
}
public int get(int key) {
if (!keyToVal.containsKey(key)) return -1;
increaseFreq(key);
return keyToVal.get(key);
}
public void put(int key, int value) {
if (capacity <= 0) return;
if (keyToVal.containsKey(key)) {
keyToVal.put(key, value);
increaseFreq(key);
return;
}
if (keyToVal.size() == capacity) {
removeMinKey();
}
keyToVal.put(key, value);
keyToFreq.put(key, 1);
freqToKeys.compute(1, (k, v) -> v == null? new LinkedHashSet<>(): v).add(key);
minFreq = 1;
}
private void increaseFreq(int key) {
int freq = keyToFreq.get(key);
freqToKeys.get(freq).remove(key);
if (freqToKeys.get(freq).isEmpty()) {
freqToKeys.remove(freq);
if (freq == minFreq)
minFreq++;
}
keyToFreq.put(key, freq + 1);
freqToKeys.compute(freq + 1, (k, v) -> v == null? new LinkedHashSet<>(): v).add(key);
}
private void removeMinKey() {
LinkedHashSet<Integer> set = freqToKeys.get(minFreq);
int key = set.iterator().next();
set.remove(key);
if (set.isEmpty()) {
freqToKeys.remove(minFreq);
}
keyToVal.remove(key);
keyToFreq.remove(key);
}

}

/**

  • Your LFUCache object will be instantiated and called as such:
  • LFUCache obj = new LFUCache(capacity);
  • int param_1 = obj.get(key);
  • obj.put(key,value);
    */
    ···
posted @   kiper  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示