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 ...
随机推荐
- 11.2.0.4 sql*loader/oci direct load导致kpodplck wait before retrying ORA-54
昨天晚上9点多,有个环境开发说特别慢,早上上去看下了,如下: 导致性能的是一个统计的sql执行计划走错了,主要不是因为kpodplck wait before retrying ORA-54,不过这个 ...
- Codeforces 799D Field expansion - 搜索 - 贪心
In one of the games Arkady is fond of the game process happens on a rectangular field. In the game p ...
- centos6.9 svn提交更新到网站根目录
一.首先创建网站根目录 ~] # mkdir -pv /export/home/cms/www_dyrs ~] # svn co svn://127.0.0.1/svn1 /export/home/c ...
- 正则表达式验证HTTP地址是否合法
转载:https://blog.csdn.net/fsdad/article/details/52637426 判断url是否合法 const std::regex urlpattern(" ...
- Python3基础 response.info 服务器返回的header信息
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- ps一些疑问知识点
PS 的核心, 是 选择, 是 抠图, 不管是蒙版, 通道也好等等, 其实主要的作用还是 抠图. 还是精确地 选出你要处理的 内容对象! 如何改变工具预设? 使用工具预设, 可以将你当前正在使用的 / ...
- linux下关于mysql的命令的用法
所有关于mysql的命令都在/usr/bin/中, 使用 /usr/bin | grep 'mysql'可以列出这些mysql命令 导出数据库, 可以直接在 命令行中, 使用 mysqldump -u ...
- 【做题】CF285E. Positions in Permutations——dp+容斥
题意:求所有长度为\(n\)的排列\(p\)中,有多少个满足:对于所有\(i \,(1 \leq i \leq n)\),其中恰好有\(k\)个满足\(|p_i - i| = 1\).答案对\(10^ ...
- 【问题解决:死锁】Lock wait timeout exceeded; try restarting transaction的问题
执行数据删除操作时一直超时并弹出Lock wait timeout exceeded; try restarting transaction错误 解决办法 1.先查看数据库的事务隔离级别 select ...
- sublime插件开发手记
原:http://blog.hickwu.com/sublime插件开发手记 标题: sublime插件开发手记 时间: 2014-01-05 14:58:02 正文: 插件基本结构 基本插件实现 ...