我是靠谱客的博主 搞怪篮球,这篇文章主要介绍LRU和LFULRULFU,现在分享给大家,希望可以做个参考。

LRU

根据题意,使用过的数据放在链表的尾部,容量满了就删除链表的头,使用的数据结构是LinkedHashMap
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

146. LRU 缓存(中等)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class LRUCache { private int cap; private LinkedHashMap<Integer, Integer> list; public LRUCache(int capacity) { this.list = new LinkedHashMap<>(); this.cap = capacity; } public int get(int key) { //cache中不存在,返回-1 if (!list.containsKey(key)) { return -1; } //存在,key变为使用过-放到哈希表末尾 makeRencentlyUsed(key);// 将 key 变为最近使⽤ return list.get(key); } /* 添加最近使⽤的元素 */ public void put(int key, int value) { //存在就更新 if (list.containsKey(key)) { list.put(key, value); makeRencentlyUsed(key);//put和get存在的话都要将key提升到最近使用的位置,即链表末尾 return; } //判断容量 if (this.cap <= list.size()) { int oldKey = list.keySet().iterator().next(); list.remove(oldKey);//不满足删除最久没有使用过的数据,即链表头节点 } list.put(key, value); } /* 将某个 key 提升为最近使⽤的 */ private void makeRencentlyUsed(int key) { int oldValue = list.get(key); list.remove(key); // 先从链表中删除这个节点 list.put(key, oldValue);// 重新插到队尾 } }

LFU

460. LFU 缓存(困难)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
class LFUCache { private HashMap<Integer, Integer> keyToValue; private HashMap<Integer, Integer> keyToFreq; private HashMap<Integer, LinkedHashSet<Integer>> freqToKey; private int cap; private int minFreq; public LFUCache(int capacity) { this.keyToValue = new HashMap<>(); this.keyToFreq = new HashMap<>(); this.freqToKey = new HashMap<>(); this.cap = capacity; this.minFreq = 0; } public int get(int key) { if (!keyToValue.containsKey(key)) { return -1; } increaseFreq(key);// 增加 key 对应的 freq return keyToValue.get(key); } public void put(int key, int value) { if (this.cap <= 0) return; /* 若 key 已存在,修改对应的 val 即可 */ if (keyToValue.containsKey(key)) { keyToValue.put(key, value); // key 对应的 freq 加一 increaseFreq(key); return; } /* key 不存在,需要插入 */ /* 容量已满的话需要淘汰一个 freq 最小的 key */ if (this.cap <= keyToValue.size()) { removeMinFreq(key); } /* 插入 key 和 val,对应的 freq 为 1 */ // 插入 KV 表 keyToValue.put(key, value); // 插入 KF 表 keyToFreq.put(key, 1); // 插入 FK 表 freqToKey.putIfAbsent(1, new LinkedHashSet<>()); // 插入新 key 后最小的 freq 肯定是 1 freqToKey.get(1).add(key); this.minFreq = 1; return; } private void increaseFreq(int key) { int oldValue = keyToFreq.get(key); keyToFreq.put(key, oldValue + 1); /* 更新 KF 表 */ /* 更新 FK 表 */ freqToKey.get(oldValue).remove(key);// 将 key 从 freq 对应的列表中删除 // 如果 freq 对应的列表空了,移除这个 freq if (freqToKey.get(oldValue).isEmpty()) { freqToKey.remove(oldValue); // 如果这个 freq 恰好是 minFreq,更新 minFreq if (minFreq == oldValue) { minFreq++; } } freqToKey.putIfAbsent(oldValue + 1, new LinkedHashSet<>());// 将 key 加入 freq + 1 对应的列表中 freqToKey.get(oldValue + 1).add(key); } private void removeMinFreq(int key) { // freq 最小的 key 列表 LinkedHashSet<Integer> list = freqToKey.get(this.minFreq); // 其中最先被插入的那个 key 就是该被淘汰的 key Integer oldKey = list.iterator().next(); /* 更新 FK 表 */ list.remove(oldKey); if (list.isEmpty()) { freqToKey.remove(this.minFreq); // 问:这里需要更新 minFreq 的值吗? } keyToValue.remove(oldKey); /* 更新 KV 表 */ keyToFreq.remove(oldKey); /* 更新 KF 表 */ } }

最后

以上就是搞怪篮球最近收集整理的关于LRU和LFULRULFU的全部内容,更多相关LRU和LFULRULFU内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部