Katkat

Build a least-recently-used cache

AnthropicSoftware Engineer · Onsite

Last updated

This problem tests your ability to implement an efficient LRU cache using a combination of a hash map and a doubly linked list to achieve constant-time operations.

LRU Cache Implementation

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

  • LRUCache(int capacity): Initialize the LRU cache with a positive size capacity.
  • int get(int key): Return the value of the key if the key exists, otherwise return -1.
  • void put(int key, int value): Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used item.

Both get and put must run in O(1) average time complexity.

Constraints

  • 1 <= capacity <= 3000
  • 0 <= key <= 10^4
  • 0 <= value <= 10^5

Example

# Initialize with capacity 2
lru = LRUCache(2)
lru.put(1, 1)
lru.put(2, 2)
lru.get(1)    # returns 1
lru.put(3, 3) # evicts key 2
lru.get(2)    # returns -1 (not found)
lru.put(4, 4) # evicts key 1
lru.get(1)    # returns -1
lru.get(3)    # returns 3
lru.get(4)    # returns 4

Implementation Template

class LRUCache:
    def __init__(self, capacity: int):
        pass

    def get(self, key: int) -> int:
        pass

    def put(self, key: int, value: int) -> None:
        pass

Hints

Hint 1

To achieve O(1) time complexity for both operations, you need to store keys in a hash map for fast lookup.

Hint 2

To track the order of usage, consider using a doubly linked list where the head represents the most recently used item and the tail represents the least recently used item.

Hint 3

When an item is accessed or updated, move it to the front of the list; when the capacity is exceeded, remove the node at the tail of the list.

Follow-up questions

  • How would you modify this implementation to be thread-safe in a multi-threaded environment?
  • If the cache needed to be distributed across multiple servers, what mechanisms would you introduce to handle cache coherence and partitioning?
  • How does your implementation change if you need to support a Time-To-Live (TTL) for each cached entry?