lru-cache.js
class LRUCache {
constructor(capacity) {
this.cap = capacity;
this.map = new Map(); // key → node
this.head = new Node(); // MRU sentinel
this.tail = new Node(); // LRU sentinel
this.head.next = this.tail;
this.tail.prev = this.head;
}
 
get(key) {
if (!this.map.has(key)) return -1;
const node = this.map.get(key);
this._moveToFront(node);
return node.val;
}
 
put(key, value) {
if (this.map.has(key)) {
const node = this.map.get(key);
node.val = value;
this._moveToFront(node);
return;
}
if (this.map.size >= this.cap) {
const lru = this.tail.prev;
this._remove(lru);
this.map.delete(lru.key);
}
const node = new Node(key, value);
this.map.set(key, node);
this._addFront(node);
}
}
Run an operation, or press Run demo to replay LeetCode 146.

Cache ready. Try get / put, or run the demo.

The two structures, in sync map + doubly-linked list
Hash map key → node · O(1)
keynode
Doubly-linked list MRU → LRU
Step log newest first