Cache & State
Implement LRU Cache
🗄️
Picture this
A librarian moves every borrowed book to the front desk; when shelves overflow, the dusty book at the back is removed.
When you see it
Signal words
If the prompt uses any of these, this pattern should come to mind first.
LRUcacheO(1)evictiongetput
Approach
Use a Map for key lookup and a doubly linked list for recency. get moves the node to the front. put updates or inserts, then evicts the tail if capacity is exceeded.
Skeleton
class Node<K, V> {
constructor(public key: K, public value: V, public prev: Node<K, V> | null = null, public next: Node<K, V> | null = null) {}
}
class LRUCache<K, V> {
private nodes = new Map<K, Node<K, V>>();
private head: Node<K, V> | null = null;
private tail: Node<K, V> | null = null;
constructor(private capacity: number) {}
get(key: K): V | undefined {
const node = this.nodes.get(key);
if (!node) return undefined;
this.moveToFront(node);
return node.value;
}
put(key: K, value: V): void {
const existing = this.nodes.get(key);
if (existing) {
existing.value = value;
this.moveToFront(existing);
return;
}
const node = new Node(key, value);
this.nodes.set(key, node);
this.addFront(node);
if (this.nodes.size > this.capacity) this.evictTail();
}
}
Watch for
Updating an existing key must refresh recency.
Eviction must remove from both the list and the map.