Implement a size-bounded LRU cache
SnapchatSoftware Engineer · OnsiteLast updated
This problem tests your ability to extend the standard LRU cache pattern to support items with heterogeneous 'weights', requiring a data structure that maintains access order while managing a cumulative capacity constraint.
Problem: Size-Bounded LRU Cache
Design and implement a thread-safe, size-bounded cache that supports storing items with variable sizes. Unlike a standard LRU cache that limits the count of elements, this cache is limited by the total sum of the weights of all stored items.
You must implement the following interface:
class WeightedLRUCache:
def __init__(self, capacity: int):
# Initialize the cache with a maximum total weight capacity.
pass
def get(self, key: int) -> int:
# Return the value if the key exists, updating its status to 'most recently used'.
# Return -1 if the key does not exist.
pass
def put(self, key: int, value: int, weight: int) -> None:
# Add/update the key-value pair with the associated weight.
# If the total weight exceeds the capacity, evict items from the 'least recently used'
# end until the total weight is within the capacity.
pass
Constraints
capacity> 0.weight> 0 for all items.- If a single item's weight exceeds the
capacity, the cache should not store it (or handle the error appropriately). getandputoperations should run in O(1) average time complexity.
Example
cache = WeightedLRUCache(10)
cache.put(1, 100, 4) # Cache: {1: 100}, Current weight: 4
cache.put(2, 200, 7) # Cache: {2: 200}, Evicts 1 (Total weight 7 10)
cache.get(1) # Returns -1
cache.get(2) # Returns 200
Edge Cases
- Updating an existing key with a new weight that forces eviction of other items.
- A new item weight being larger than the total cache capacity.
- Repeatedly calling
putwith the same key.
Hints
Hint 1
Use a doubly linked list to maintain the access order of keys and a hash map to map keys to their corresponding nodes.
Hint 2
Store the 'weight' as a property within each node of the linked list to allow for quick subtraction from the current total weight when an eviction occurs.
Hint 3
In the 'put' method, check if the key already exists; if it does, remove the old node and its weight before adding the new node, then evict the tail of the list while the total current weight exceeds capacity.
Follow-up questions
- How would you modify this implementation to handle multi-threaded access while minimizing lock contention?
- If the cache needs to be distributed across multiple physical machines, what strategies would you use to partition the keys?
- How does the performance of this cache change if the distribution of 'weights' is highly skewed?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.