Katkat

Build an LRU Cache with a Hash Map and Linked List

AmazonSoftware Engineer · HR Screen

Last updated

This problem tests your ability to design a cache with O(1) time complexity for both get and put operations by combining a hash map with a doubly linked list.

LRU Cache Design

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

  • get(key): Return the value of the key if the key exists, otherwise return -1.
  • put(key, value): Update the value of the key if it exists. Otherwise, add the key-value pair to the cache. If the cache reaches its capacity, it should invalidate the least recently used item before inserting a new item.

Your implementation must support both operations in O(1) average time complexity.

Requirements

  • Class LRUCache with __init__(self, capacity: int)
  • get(key: int) -> int
  • put(key: int, value: int) -> None

Example

lru = LRUCache(2)
lru.put(1, 1)    # cache is {1=1}
lru.put(2, 2)    # cache is {1=1, 2=2}
lru.get(1)       # returns 1, cache is {2=2, 1=1}
lru.put(3, 3)    # evicts key 2, cache is {1=1, 3=3}
lru.get(2)       # returns -1 (not found)
lru.put(4, 4)    # evicts key 1, cache is {3=3, 4=4}
lru.get(1)       # returns -1 (not found)
lru.get(3)       # returns 3
lru.get(4)       # returns 4

Constraints

  • Capacity is a positive integer.
  • Keys and values are integers.
  • Ensure the cache handles updating an existing key's value correctly by treating it as a "use" (making it the most recent).

Hints

Hint 1

Use a hash map to store keys mapped to nodes in a doubly linked list for O(1) access.

Hint 2

A doubly linked list allows for O(1) removal and insertion of nodes if you maintain pointers to the head and tail.

Hint 3

Whenever a `get` or `put` operation is performed on a key, move the corresponding node to the head of the linked list to mark it as the most recently used.

Follow-up questions

  • How would you modify this implementation to be thread-safe in a multi-threaded environment?
  • What would change if you wanted to implement an LFU (Least Frequently Used) cache instead of an LRU cache?
  • How does the performance of this cache degrade if the hash map experiences frequent collisions?