LRU Cache
Least Recently Used cache with O(1) operations
LRU Cache
An LRU Cache evicts the least recently used item when full. It combines a hash map (O(1) lookup) with a doubly linked list (O(1) removal and insertion) to achieve O(1) for both get and put. This is one of the most popular interview questions.
LRU Cache Structure
typescript
// LRU Cache Implementation
class DLLNode {
key: number; val: number;
prev: DLLNode | null = null;
next: DLLNode | null = null;
constructor(key: number, val: number) { this.key = key; this.val = val; }
}
class LRUCache {
private capacity: number;
private map = new Map<number, DLLNode>();
private head = new DLLNode(0, 0); // dummy
private tail = new DLLNode(0, 0); // dummy
constructor(capacity: number) {
this.capacity = capacity;
this.head.next = this.tail;
this.tail.prev = this.head;
}
get(key: number): number {
const node = this.map.get(key);
if (!node) return -1;
this.moveToHead(node);
return node.val;
}
put(key: number, value: number): void {
if (this.map.has(key)) {
const node = this.map.get(key)!;
node.val = value;
this.moveToHead(node);
} else {
const node = new DLLNode(key, value);
this.map.set(key, node);
this.addToHead(node);
if (this.map.size > this.capacity) {
const lru = this.tail.prev!;
this.remove(lru);
this.map.delete(lru.key);
}
}
}
private addToHead(node: DLLNode): void {
node.prev = this.head;
node.next = this.head.next;
this.head.next!.prev = node;
this.head.next = node;
}
private remove(node: DLLNode): void {
node.prev!.next = node.next;
node.next!.prev = node.prev;
}
private moveToHead(node: DLLNode): void {
this.remove(node);
this.addToHead(node);
}
}💬 Can you implement LRU Cache using JavaScript's built-in Map?
Yes! JavaScript's Map maintains insertion order. You can delete and re-insert a key to move it to the end (most recent). To evict, use map.keys().next().value to get the oldest key. This gives you O(1) operations without implementing a doubly linked list.