Difficulty: Medium-Hard | Asked at: Amazon, Google, Meta
Design a Least Recently Used (LRU) cache with O(1)
get and put operations.
cache = LRUCache(2)
cache.put(1, 1)
cache.put(2, 2)
cache.get(1) # returns 1, and marks 1 as recently used
cache.put(3, 3) # evicts key 2 (least recently used)
cache.get(2) # returns -1 (not found)
💡 Hint: This is the perfect combo problem - you need O(1) lookup (hash map) AND O(1) reordering/eviction (doubly linked list). Neither alone gets you there.
Solution:
python
class Node:
def __init__(self, key, val):
self.key = key
self.val = val
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity):
self.capacity = capacity
self.cache = {}
self.head = Node(0, 0)
self.tail = Node(0, 0)
self.head.next = self.tail
self.tail.prev = self.head
def _remove(self, node):
node.prev.next = node.next
node.next.prev = node.prev
def _add_to_front(self, node):
node.next = self.head.next
node.prev = self.head
self.head.next.prev = node
self.head.next = node
def get(self, key):
if key not in self.cache:
return -1
node = self.cache[key]
self._remove(node)
self._add_to_front(node)
return node.val
def put(self, key, value):
if key in self.cache:
self._remove(self.cache[key])
node = Node(key, value)
self.cache[key] = node
self._add_to_front(node)
if len(self.cache) > self.capacity:
lru = self.tail.prev
self._remove(lru)
del self.cache[lru.key]
Complexity: O(1) time for both
get and put, O(capacity) space.Common mistake: Trying to use Python's built-in
list to track recency order - list.remove() and re-inserting are O(n), which defeats the entire point. The doubly linked list is what makes removal from the middle O(1), because you don't need to search for the node - you already have a direct reference to it.💡 Pro tip: in a real interview, mentioning
OrderedDict in Python (which has built-in move_to_end()) is a great way to show you know the language deeply - but building it from scratch with a hash map + linked list is what interviewers actually want to see, since it proves you understand WHY it's O(1), not just that a library exists.This is consistently rated one of the best "combines two data structures" interview questions. Have you built this before, or is this your first time seeing it? 👇