LFU Cache - Problem
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
Key Operations:
•
•
•
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.
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
✓ Linear Growth
Space Complexity
O(capacity)
Hash map + doubly-linked list nodes + frequency buckets, all proportional to capacity
✓ Linear Space
Constraints
- 0 ≤ capacity ≤ 104
- 0 ≤ key ≤ 105
- 0 ≤ value ≤ 109
-
At most 2 × 105 calls will be made to
getandput - Both operations must run in O(1) average time complexity
💡
Explanation
AI Ready
💡 Suggestion
Tab
to accept
Esc
to dismiss
// Output will appear here after running code