@@ -29,97 +29,99 @@ cache.get(4); // returns 4
2929```
3030
3131## 思路
32+
33+ ` 本题已被收录到我的新书中,敬请期待~ `
34+
3235[ LFU(Least frequently used)] ( https://www.wikiwand.com/en/Least_frequently_used ) 但内存容量满的情况下,有新的数据进来,需要更多空间的时候,就需要删除被访问频率最少的元素。
3336
34- 举个例子,比如说cache容量是 3,按顺序依次放入 ` 1,2,1,2,1,3 ` , cache已存满 3 个元素 (1,2,3), 这时如果想放入一个新的元素 4 的时候,就需要腾出一个元素空间。
37+ 举个例子,比如说 cache 容量是 3,按顺序依次放入 ` 1,2,1,2,1,3 ` , cache 已存满 3 个元素 (1,2,3), 这时如果想放入一个新的元素 4 的时候,就需要腾出一个元素空间。
3538用 LFU,这里就淘汰 3, 因为 3 的次数只出现依次, 1 和 2 出现的次数都比 3 多。
3639
37-
3840题中 ` get ` 和 ` put ` 都是 ` O(1) ` 的时间复杂度,那么删除和增加都是` O(1) ` ,可以想到用双链表,和` HashMap ` ,用一个` HashMap, nodeMap, ` 保存当前` key ` ,和 ` node{key, value, frequent} ` 的映射。
3941这样` get(key) ` 的操作就是` O(1) ` . 如果要删除一个元素,那么就需要另一个` HashMap,freqMap, ` 保存元素出现次数` (frequent) ` 和双链表` (DoublyLinkedlist) ` 映射,
40- 这里双链表存的是frequent相同的元素 。每次` get ` 或` put ` 的时候,` frequent+1 ` ,然后把` node ` 插入到双链表的` head node, head.next=node `
42+ 这里双链表存的是 frequent 相同的元素 。每次` get ` 或` put ` 的时候,` frequent+1 ` ,然后把` node ` 插入到双链表的` head node, head.next=node `
4143每次删除` freqent ` 最小的双链表的` tail node, tail.prev ` 。
4244
4345用给的例子举例说明:
4446 ```
4547 1. put(1, 1),
46- - 首先查找nodeMap中有没有key=1对应的value ,
47- 没有就新建node (key, value, freq) -> node1(1, 1, 1), 插入 nodeMap,{[1, node1]}
48- - 查找freqMap中有没有freq =1 对应的value ,
49- 没有就新建doublylinkedlist (head, tail), 把node1 插入doublylinkedlist head->next = node1.
48+ - 首先查找 nodeMap 中有没有 key=1 对应的 value ,
49+ 没有就新建 node (key, value, freq) -> node1(1, 1, 1), 插入 nodeMap,{[1, node1]}
50+ - 查找 freqMap 中有没有 freq =1 对应的 value ,
51+ 没有就新建 doublylinkedlist (head, tail), 把 node1 插入 doublylinkedlist head->next = node1.
5052 如下图,
5153 ```
5254![ 460.lfu-cache-1] ( ../assets/problems/460.lfu-cache-1.jpg )
5355 ```
5456 2. put(2, 2),
55- - 首先查找nodeMap中有没有key=2对应的value ,
56- 没有就新建node (key, value, freq) -> node2(2, 2, 1), 插入 nodeMap,{[1, node1], [2, node2]}
57- - 查找freqMap中有没有freq =1 对应的value ,
58- 没有就新建doublylinkedlist (head, tail), 把node2 插入doublylinkedlist head->next = node2.
57+ - 首先查找 nodeMap 中有没有 key=2 对应的 value ,
58+ 没有就新建 node (key, value, freq) -> node2(2, 2, 1), 插入 nodeMap,{[1, node1], [2, node2]}
59+ - 查找 freqMap 中有没有 freq =1 对应的 value ,
60+ 没有就新建 doublylinkedlist (head, tail), 把 node2 插入 doublylinkedlist head->next = node2.
5961 如下图,
6062 ```
6163![ 460.lfu-cache-2] ( ../assets/problems/460.lfu-cache-2.jpg )
6264 ```
6365 3. get(1),
64- - 首先查找nodeMap中有没有key=1对应的value ,nodeMap:{[1, node1], [2, node2]},
65- 找到node1,把node1 freq+1 -> node1(1,1,2)
66- - 更新freqMap,删除freq =1,node1
67- - 更新freqMap,插入freq =2,node1
66+ - 首先查找 nodeMap 中有没有 key=1 对应的 value ,nodeMap:{[1, node1], [2, node2]},
67+ 找到 node1,把 node1 freq+1 -> node1(1,1,2)
68+ - 更新 freqMap,删除 freq =1,node1
69+ - 更新 freqMap,插入 freq =2,node1
6870 如下图,
6971 ```
7072![ 460.lfu-cache-3] ( ../assets/problems/460.lfu-cache-3.jpg )
7173 ```
7274 4. put(3, 3),
73- - 判断cache的capacity ,已满,需要淘汰使用次数最少的元素,找到最小的freq =1,删除双链表tail node.prev
74- 如果tailnode .prev != null, 删除。然后从nodeMap中删除对应的key 。
75- - 首先查找nodeMap中有没有key=3对应的value ,
76- 没有就新建node (key, value, freq) -> node3(3, 3, 1), 插入 nodeMap,{[1, node1], [3, node3]}
77- - 查找freqMap中有没有freq =1 对应的value ,
78- 没有就新建doublylinkedlist (head, tail), 把node3 插入doublylinkedlist head->next = node3.
75+ - 判断 cache 的 capacity ,已满,需要淘汰使用次数最少的元素,找到最小的 freq =1,删除双链表 tail node.prev
76+ 如果 tailnode .prev != null, 删除。然后从 nodeMap 中删除对应的 key 。
77+ - 首先查找 nodeMap 中有没有 key=3 对应的 value ,
78+ 没有就新建 node (key, value, freq) -> node3(3, 3, 1), 插入 nodeMap,{[1, node1], [3, node3]}
79+ - 查找 freqMap 中有没有 freq =1 对应的 value ,
80+ 没有就新建 doublylinkedlist (head, tail), 把 node3 插入 doublylinkedlist head->next = node3.
7981 如下图,
8082 ```
8183![ 460.lfu-cache-4] ( ../assets/problems/460.lfu-cache-4.jpg )
8284 ```
8385 5. get(2)
84- - 查找nodeMap,如果没有对应的key的value ,返回 -1。
86+ - 查找 nodeMap,如果没有对应的 key 的 value ,返回 -1。
8587
8688 6. get(3)
87- - 首先查找nodeMap中有没有key=3对应的value ,nodeMap:{[1, node1], [3, node3]},
88- 找到node3,把node3 freq+1 -> node3(3,3,2)
89- - 更新freqMap,删除freq =1,node3
90- - 更新freqMap,插入freq =2,node3
89+ - 首先查找 nodeMap 中有没有 key=3 对应的 value ,nodeMap:{[1, node1], [3, node3]},
90+ 找到 node3,把 node3 freq+1 -> node3(3,3,2)
91+ - 更新 freqMap,删除 freq =1,node3
92+ - 更新 freqMap,插入 freq =2,node3
9193 如下图,
9294 ```
9395![ 460.lfu-cache-5] ( ../assets/problems/460.lfu-cache-5.jpg )
9496 ```
9597 7. put(4, 4),
96- - 判断cache的capacity ,已满,需要淘汰使用次数最少的元素,找到最小的freq =1,删除双链表tail node.prev
97- 如果tailnode .prev != null, 删除。然后从nodeMap中删除对应的key 。
98- - 首先查找nodeMap中有没有key=4对应的value ,
99- 没有就新建node (key, value, freq) -> node4(4, 4, 1), 插入 nodeMap,{[4, node4], [3, node3]}
100- - 查找freqMap中有没有freq =1 对应的value ,
101- 没有就新建doublylinkedlist (head, tail), 把 node4 插入doublylinkedlist head->next = node4.
98+ - 判断 cache 的 capacity ,已满,需要淘汰使用次数最少的元素,找到最小的 freq =1,删除双链表 tail node.prev
99+ 如果 tailnode .prev != null, 删除。然后从 nodeMap 中删除对应的 key 。
100+ - 首先查找 nodeMap 中有没有 key=4 对应的 value ,
101+ 没有就新建 node (key, value, freq) -> node4(4, 4, 1), 插入 nodeMap,{[4, node4], [3, node3]}
102+ - 查找 freqMap 中有没有 freq =1 对应的 value ,
103+ 没有就新建 doublylinkedlist (head, tail), 把 node4 插入 doublylinkedlist head->next = node4.
102104 如下图,
103105 ```
104106![ 460.lfu-cache-6] ( ../assets/problems/460.lfu-cache-6.jpg )
105107 ```
106108 8. get(1)
107- - 查找nodeMap,如果没有对应的key的value ,返回 -1。
109+ - 查找 nodeMap,如果没有对应的 key 的 value ,返回 -1。
108110
109111 9. get(3)
110- - 首先查找nodeMap中有没有key=3对应的value ,nodeMap:{[4, node4], [3, node3]},
111- 找到node3,把node3 freq+1 -> node3(3,3,3)
112- - 更新freqMap,删除freq =2,node3
113- - 更新freqMap,插入freq =3,node3
112+ - 首先查找 nodeMap 中有没有 key=3 对应的 value ,nodeMap:{[4, node4], [3, node3]},
113+ 找到 node3,把 node3 freq+1 -> node3(3,3,3)
114+ - 更新 freqMap,删除 freq =2,node3
115+ - 更新 freqMap,插入 freq =3,node3
114116 如下图,
115117 ```
116118![ 460.lfu-cache-7] ( ../assets/problems/460.lfu-cache-7.jpg )
117119 ```
118120 10. get(4)
119- - 首先查找nodeMap中有没有key=4对应的value ,nodeMap:{[4, node4], [3, node3]},
120- 找到node4,把node4 freq+1 -> node4(4,4,2)
121- - 更新freqMap,删除freq =1,node4
122- - 更新freqMap,插入freq =2,node4
121+ - 首先查找 nodeMap 中有没有 key=4 对应的 value ,nodeMap:{[4, node4], [3, node3]},
122+ 找到 node4,把 node4 freq+1 -> node4(4,4,2)
123+ - 更新 freqMap,删除 freq =1,node4
124+ - 更新 freqMap,插入 freq =2,node4
123125 如下图,
124126 ```
125127![ 460.lfu-cache-8] ( ../assets/problems/460.lfu-cache-8.jpg )
@@ -128,7 +130,7 @@ cache.get(4); // returns 4
128130用两个` Map ` 分别保存 ` nodeMap {key, node} ` 和 ` freqMap{frequent, DoublyLinkedList} ` 。
129131实现` get ` 和 ` put ` 操作都是` O(1) ` 的时间复杂度。
130132
131- 可以用Java自带的一些数据结构,比如HashLinkedHashSet,这样就不需要自己自建Node ,DoublelyLinkedList。
133+ 可以用 Java 自带的一些数据结构,比如 HashLinkedHashSet,这样就不需要自己自建 Node ,DoublelyLinkedList。
132134可以很大程度的缩减代码量。
133135
134136## 代码(Java code)
0 commit comments