# 460. LFU Cache

Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: `get` and `put`.

`get(key)` - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
`put(key, value)` - Set or insert the value if the key is not already present. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when there is a tie (i.e., two or more keys that have the same frequency), the least recently used key would be evicted.

Could you do both operations in O(1) time complexity?

Example:

``````LFUCache cache = new LFUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(3);       // returns 3.
cache.put(4, 4);    // evicts key 1.
cache.get(3);       // returns 3
cache.get(4);       // returns 4
``````

m:

5 -> {value5, 1}

4 -> {value4, 1}

freq:

1 -> {5，4}

iter:

4 -> list.begin() + 1

5 -> list.begin()

1. 如果m中不存在5，那么返回-1

2. 从freq中频率为1的list中将5删除

3. 将m中5对应的frequence值自增1

4. 将5保存到freq中频率为2的list的末尾

5. 在iter中保存5在freq中频率为2的list中的位置

6. 如果freq中频率为minFreq的list为空，minFreq自增1

7. 返回m中5对应的value值

m:

5 -> {value5, 2}

4 -> {value4, 1}

freq:

1 -> {4}

2 -> {5}

iter:

4 -> list.begin()

5 -> list.begin()

1. 如果调用get(7)返回的结果不是-1，那么在将m中7对应的value更新为当前value，并返回

2. 如果此时m的大小大于了cap，即超过了cache的容量，则：

a）在m中移除minFreq对应的list的首元素的纪录，即移除4 -> {value4, 1}

b）在iter中清除4对应的纪录，即移除4 -> list.begin()

c）在freq中移除minFreq对应的list的首元素，即移除4

3. 在m中建立7的映射，即 7 -> {value7, 1}

4. 在freq中频率为1的list末尾加上7

5. 在iter中保存7在freq中频率为1的list中的位置

6. minFreq重置为1

m:

5 -> {value5, 2}

7 -> {value7, 1}

freq:

1 -> {7}

2 -> {5}

iter:

7 -> list.begin()

5 -> list.begin()

``````class LFUCache {
public:
LFUCache(int capacity) {
cap = capacity;
}

int get(int key) {
if (m.count(key) == 0) return -1;
freq[m[key].second].erase(iter[key]);
++m[key].second;
freq[m[key].second].push_back(key);
iter[key] = --freq[m[key].second].end();
if (freq[minFreq].size() == 0) ++minFreq;
return m[key].first;
}

void put(int key, int value) {
if (cap <= 0) return;
if (get(key) != -1) {
m[key].first = value;
return;
}
if (m.size() >= cap) {
m.erase(freq[minFreq].front());
iter.erase(freq[minFreq].front());
freq[minFreq].pop_front();
}
m[key] = {value, 1};
freq[1].push_back(key);
iter[key] = --freq[1].end();
minFreq = 1;
}

private:
int cap, minFreq;
unordered_map<int, pair<int, int>> m;
unordered_map<int, list<int>> freq;
unordered_map<int, list<int>::iterator> iter;
};
``````

LRU Cache

https://leetcode.com/problems/lfu-cache/

https://discuss.leetcode.com/topic/69436/concise-c-o-1-solution-using-3-hash-maps-with-explanation

LeetCode All in One 题目讲解汇总(持续更新中…)

 微信打赏 Venmo 打赏
（欢迎加入博主的知识星球，博主将及时答疑解惑，并分享刷题经验与总结，试运营期间前五十位可享受半价优惠～）

×

Help us with donation