LFU Cache
2018-11-06 20:06:04
LFU(Least Frequently Used)算法根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。
如何高效的实现一个LFU Cache是一个难点,其实现方式要比LRU要复杂一点,问题的核心就是如果对不同的freq进行计数和维护。这里用到的思路和最大频率栈是类似的,也就是对每个freq都开辟一个Set来进行单独的维护。

为了实现的方便,我们可以在每个freq节点中放入一个LinkedHashSet,这样就可以很方便的进行编码。
public class LFUCache {
private FreqNode head;
private FreqNode tail;
private HashMap<Integer, Integer> key2val;
private HashMap<Integer, FreqNode> key2node;
private int capacity;
public LFUCache(int capacity) {
this.capacity = capacity;
this.head = new FreqNode(0);
this.tail = new FreqNode(Integer.MAX_VALUE);
this.key2val = new HashMap<>();
this.key2node = new HashMap<>();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
if (capacity == 0) return -1;
if (key2val.containsKey(key)) {
int res = key2val.get(key);
increaseFreq(key);
return res;
}
return -1;
}
public void put(int key, int value) {
if (capacity == 0) return;
if (key2val.containsKey(key)) {
key2val.put(key, value);
increaseFreq(key);
}
else {
maintainSize();
key2val.put(key, value);
key2node.put(key, head);
head.keys.add(key);
increaseFreq(key);
}
}
private void increaseFreq(int key) {
FreqNode cur = key2node.get(key);
FreqNode next = null;
if (cur.next.freq == cur.freq + 1) {
next = cur.next;
}
else {
next = new FreqNode(cur.freq + 1);
next.next = cur.next;
cur.next.prev = next;
cur.next = next;
next.prev = cur;
}
next.keys.add(key);
cur.keys.remove(key);
key2node.put(key, next);
if (cur.keys.size() == 0 && cur != head) delete(cur);
}
private void maintainSize() {
if (key2val.size() >= capacity) {
FreqNode cur = head.next;
Iterator<Integer> iter = cur.keys.iterator();
int key = iter.next();
key2val.remove(key);
key2node.remove(key);
cur.keys.remove(key);
if (cur.keys.size() == 0) delete(cur);
}
}
private void delete(FreqNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
}
class FreqNode {
public int freq;
public FreqNode prev ;
public FreqNode next;
public LinkedHashSet<Integer> keys;
public FreqNode(int freq) {
this.freq = freq;
prev = null;
next = null;
keys = new LinkedHashSet<>();
}
}
/**
* 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);
*/
LFU Cache的更多相关文章
- [LeetCode] LFU Cache 最近最不常用页面置换缓存器
Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the f ...
- Leetcode: LFU Cache && Summary of various Sets: HashSet, TreeSet, LinkedHashSet
Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the f ...
- LeetCode LFU Cache
原题链接在这里:https://leetcode.com/problems/lfu-cache/?tab=Description 题目: Design and implement a data str ...
- [LeetCode] 460. LFU Cache 最近最不常用页面置换缓存器
Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the f ...
- leetcode 146. LRU Cache 、460. LFU Cache
LRU算法是首先淘汰最长时间未被使用的页面,而LFU是先淘汰一定时间内被访问次数最少的页面,如果存在使用频度相同的多个项目,则移除最近最少使用(Least Recently Used)的项目. LFU ...
- Leetcode:LRU Cache,LFU Cache
在Leetcode上遇到了两个有趣的题目,分别是利用LRU和LFU算法实现两个缓存.缓存支持和字典一样的get和put操作,且要求两个操作的时间复杂度均为O(1). 首先说一下如何在O(1)时间复杂度 ...
- leetcode 460. LFU Cache
hash:存储的key.value.freq freq:存储的freq.key,也就是说出现1次的所有key在一起,用list连接 class LFUCache { public: LFUCache( ...
- [LeetCode] LRU Cache 最近最少使用页面置换缓存器
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- 页面置换算法 - FIFO、LFU、LRU
缓存算法(页面置换算法)-FIFO. LFU. LRU 在前一篇文章中通过leetcode的一道题目了解了LRU算法的具体设计思路,下面继续来探讨一下另外两种常见的Cache算法:FIFO. LFU ...
随机推荐
- 写给大忙人的spring cloud 1.x学习指南
这几天抽空搞了下spring cloud 1.x(2.0目前应该来说还不成熟),因为之前项目中使用dubbo以及自研的rpc框架,所以总体下来还是比较顺利,加上spring boot,不算笔记整理,三 ...
- Huffman Implementation with Python
Huffman Implementation with Python 码表 Token Frequency a 10 e 15 i 12 s 3 t 4 space 13 n 1 生成 Huffman ...
- 20145311王亦徐 《网络对抗技术》 Web安全基础实践
2014531王亦徐 <网络对抗技术> Web安全基础实践 实验内容 利用WebGoat平台尝试了一些XSS.CSRF.SQL注入攻击 基础问题回答 1.SQL注入攻击原理,如何防御原理: ...
- Codeforces 437D The Child and Zoo - 树分治 - 贪心 - 并查集 - 最大生成树
Of course our child likes walking in a zoo. The zoo has n areas, that are numbered from 1 to n. The ...
- 彻底地/ 终于地, 解决 关于apache 权限的问题了:: 修改 DocumentRoot后的 403错误: have no permission to access / on this server
目录的权限都 应该设置 为 drwxr_xr_x, 即755, 而html下的文件的权限设置为; 644 即可! -x 只有目标文件对某些用户是可执行的或该目标文件是目录时才追加x 属性. -w权限, ...
- hihoCoder week15 最近公共祖先·二
tarjan求lca 就是dfs序中用并查集维护下,当访问到询问的第二个点u的时候 lca就是第一点的find(fa[v]) fa[v] = u; // 当v为u的儿子 且 v已经dfs完毕 #i ...
- [ECharts] - ECharts使用中国地图
格式1: https://www.cnblogs.com/luna666/p/9007263.html (非官方) <!DOCTYPE html> <html lang=" ...
- ngnix简介以及如何实现负载均衡原理
1 负载均衡 先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可以解释N台服务器平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况.那么负载均衡的前提就是要有多台服务器才能实现, ...
- cmd中utf-8编码的问题
有时候我们需要使用cmd显示某个utf-8编码的文本,这时候就需要设置cmd的代码页为65100. 也就是 chcp 65001 这条命令.这样设置可以临时生效. 如何要永久生效,需要在注册表中修改. ...
- C#端加载数据库,Combobox与Node控件绑定数据源demo示例
最近一直在做网页.用的js比较多,最近需要做一个C#相关的demo,一开始还有点不适应,写了几句有点感觉了 本篇博客的主要内容是C#怎么读取数据库文件里的数据以及相关控件如何绑定数据源,所做的Demo ...