LFU Cache

O(1) LFU — per-frequency LRU bucket, key map, and an evolving min-freq counter.

Hard
Time O(1) per op Space O(capacity)
LeetCode
6 min read
design hash-map linked-list lfu

Problem#

LFU cache with get and put in O(1). Evict the least-frequently-used key on overflow; break ties by least-recently-used within that frequency.

Examples#

  • cap=2; put(1,1); put(2,2); get(1); put(3,3) evicts 2 (freq 1 vs key 1’s freq 2).
  • get(2)-1 after eviction.

Constraints#

  • 0 <= capacity <= 10^4, up to 2 * 10^5 ops.

Approach#

Three maps: key → (value, freq, iterator into bucket); freq → list<int> of keys (each bucket is an LRU ordered by recency); a minFreq counter. Every access bumps the key’s freq, splicing it to the new bucket; on overflow, evict the back of freq[minFreq].

Solution#

LFU Cache
class LFUCache {
int cap, minFreq = 0;
unordered_map<int, tuple<int,int,list<int>::iterator>> kv; // key -> {val, freq, it}
unordered_map<int, list<int>> buckets; // freq -> LRU list of keys
void touch(int key) {
auto& [val, f, it] = kv[key];
buckets[f].erase(it);
if (buckets[f].empty() && f == minFreq) ++minFreq;
++f;
buckets[f].push_front(key);
it = buckets[f].begin();
}
public:
LFUCache(int capacity) : cap(capacity) {}
int get(int key) {
if (!kv.count(key)) return -1;
int v = get<0>(kv[key]);
touch(key);
return v;
}
void put(int key, int value) {
if (cap == 0) return;
if (kv.count(key)) {
get<0>(kv[key]) = value;
touch(key);
return;
}
if ((int)kv.size() == cap) {
int evict = buckets[minFreq].back();
buckets[minFreq].pop_back();
kv.erase(evict);
}
buckets[1].push_front(key);
kv[key] = {value, 1, buckets[1].begin()};
minFreq = 1;
}
};

Editorial#

The key insight: within a single frequency bucket, recency order is exactly LRU, so popping the back evicts the right tie. minFreq only ever increases between touches and resets to 1 on insertion — never need to scan for it. All ops are O(1) amortized.

Complexity#

  • Time: O(1) per op.
  • Space: O(capacity).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.