Design and implement a Least Frequently Used (LFU) Cache - one of the most challenging cache eviction policies used in real-world systems!

Your task is to create an LFUCache class that efficiently manages data with limited capacity. When the cache is full and you need to insert a new item, you must evict the least frequently used key. If there's a tie in frequency, evict the least recently used among them.

Key Operations:
LFUCache(capacity): Initialize the cache with given capacity
get(key): Return the value if key exists, otherwise -1. This counts as a use!
put(key, value): Insert or update the key-value pair. This also counts as a use!

The Challenge: Both operations must run in O(1) average time - no linear searches allowed! This requires a sophisticated combination of hash tables and doubly-linked lists to track both frequency and recency efficiently.

Real-world application: Operating systems use LFU caching for memory management, CDNs use it for content delivery, and databases use it for buffer pool management.

Input & Output

example_1.py — Basic LFU Operations
$ Input: ["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get", "get"] [[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]]
Output: [null, null, null, 1, null, -1, 3, null, -1, 3, 4]
💡 Note: Cache capacity is 2. put(1,1), put(2,2), get(1) returns 1 and increases freq of key 1. put(3,3) evicts key 2 (freq 1, older than key 1). get(2) returns -1 (evicted). get(3) returns 3. put(4,4) evicts key 1 (freq 2 vs key 3 freq 2, but key 1 is older). Final cache contains keys 3 and 4.
example_2.py — Frequency Tie-Breaking
$ Input: ["LFUCache", "put", "put", "put", "put", "get", "get", "get", "get", "put", "get"] [[2], [3, 1], [2, 1], [2, 2], [4, 4], [2], [3], [2], [3], [5, 5], [2]]
Output: [null, null, null, null, null, 2, 1, 2, 1, null, 2]
💡 Note: Capacity 2: put(3,1), put(2,1) evicts key 3, put(2,2) updates key 2, put(4,4) adds key 4. After gets, both keys have freq 2, but when put(5,5) needs space, key 3 is evicted as it's older among freq-2 keys.
example_3.py — Capacity 1 Edge Case
$ Input: ["LFUCache", "put", "get", "put", "get", "put", "get"] [[1], [2, 1], [2], [3, 2], [2], [3], [3]]
Output: [null, null, 1, null, -1, null, 2]
💡 Note: With capacity 1, each new put() evicts the previous key. put(2,1), get(2) returns 1, put(3,2) evicts key 2, get(2) returns -1, put(3,2) updates key 3, get(3) returns 2.

Time & Space Complexity

Time Complexity
⏱️
O(1)

Hash map provides O(1) lookup, doubly-linked list provides O(1) insertion/deletion, frequency buckets provide O(1) LFU access

n
2n
Linear Growth
Space Complexity
O(capacity)

Hash map + doubly-linked list nodes + frequency buckets, all proportional to capacity

n
2n
Linear Space

Constraints

  • 0 ≤ capacity ≤ 104
  • 0 ≤ key ≤ 105
  • 0 ≤ value ≤ 109
  • At most 2 × 105 calls will be made to get and put
  • Both operations must run in O(1) average time complexity
Asked in
25.0K Views
Medium Frequency
~15 min Avg. Time
850 Likes
Ln 1, Col 1
Smart Actions
💡 Explanation
AI Ready
💡 Suggestion Tab to accept Esc to dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen