Katkat

Simulate a Least Recently Used Cache

OracleSoftware Engineer · Onsite

Last updated

This problem tests your ability to maintain data access recency and perform cache evictions in O(1) time complexity using a combination of a hash map and a doubly linked list.

LRU Cache Implementation

Design and implement a data structure for a Least Recently Used (LRU) cache. The cache must support two main operations: get(key) and put(key, value).

Requirements

  • get(key): Return the value of the key if the key exists, otherwise return -1. Accessing a key marks it as the most recently used.
  • put(key, value): Update the value of the key if it exists. Otherwise, add the key-value pair to the cache. If the cache exceeds its capacity, evict the least recently used item before adding the new one.
  • Both operations must run in O(1) average time complexity.

Class Interface

class LRUCache:
    def __init__(self, capacity: int):
        # Initialize the cache with a positive capacity
        pass

    def get(self, key: int) -> int:
        # Return value or -1
        pass

    def put(self, key: int, value: int) -> None:
        # Add or update value; evict if capacity is exceeded
        pass

Examples

cache = LRUCache(2)
cache.put(1, 1)  # Cache is {1=1}
cache.put(2, 2)  # Cache is {1=1, 2=2}
cache.get(1)     # Returns 1, Cache is {2=2, 1=1}
cache.put(3, 3)  # Evicts key 2, Cache is {1=1, 3=3}
cache.get(2)     # Returns -1 (not found)

Edge Cases

  • Accessing a key that does not exist.
  • Updating a key that already exists.
  • Calling put when the cache is at full capacity.
  • A capacity of 1.

Hints

Hint 1

Consider using a hash map to achieve O(1) lookups for keys.

Hint 2

To maintain order in O(1) time, use a doubly linked list where the head represents the most recently used item and the tail the least recently used.

Hint 3

You can combine the hash map and the linked list by storing nodes of the list as values in the hash map.

Follow-up questions

  • How would you make this thread-safe in a multi-threaded environment?
  • What would change if you needed to implement a Least Frequently Used (LFU) cache instead?
  • How would you handle the memory management if the values stored in the cache were very large objects?