79. LRU Cache
mediumAsked at VercelDesign a Least-Recently-Used cache with O(1) get and put. Vercel asks this constantly — they literally maintain LRU caches at every edge POP and want to see if you can implement one with a doubly-linked list and a hash map.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Vercel loops.
- Glassdoor (2025-Q4)— Vercel edge-runtime onsite; expected at every onsite.
- Blind (2026-Q1)— Listed as the single most likely Vercel system-design-ish problem.
Problem
Design a data structure that follows the constraints of a Least Recently Used (LRU) cache. Implement the LRUCache class: LRUCache(int capacity) initializes the cache with positive size capacity; int get(int key) returns the value of the key if it exists, otherwise -1; void put(int key, int value) updates the value of the key or inserts the key-value pair. If the number of keys exceeds capacity, evict the least recently used key. The functions get and put must each run in O(1) average time complexity.
Constraints
1 <= capacity <= 30000 <= key <= 10^40 <= value <= 10^5At most 2 * 10^5 calls will be made to get and put.
Examples
Example 1
["LRUCache","put","put","get","put","get","put","get","get","get"]
[[2],[1,1],[2,2],[1],[3,3],[2],[4,4],[1],[3],[4]][null,null,null,1,null,-1,null,-1,3,4]Approaches
1. Map with timestamp tracking
Store (value, timestamp); on eviction, scan for the oldest.
- Time
- O(n) eviction
- Space
- O(n)
// O(n) eviction. Vercel rejects this.Tradeoff: Eviction is O(n).
2. Doubly linked list + hash map (optimal)
Hash map: key -> DLL node. DLL ordered by recency. On access: move node to front. On eviction: remove tail. Dummy head/tail simplify edge cases.
- Time
- O(1) per op
- Space
- O(capacity)
class LRUCache {
constructor(capacity) {
this.cap = capacity;
this.map = new Map();
this.head = { prev: null, next: null };
this.tail = { prev: null, next: null };
this.head.next = this.tail;
this.tail.prev = this.head;
}
_remove(n) { n.prev.next = n.next; n.next.prev = n.prev; }
_addFront(n) {
n.next = this.head.next; n.prev = this.head;
this.head.next.prev = n; this.head.next = n;
}
get(key) {
if (!this.map.has(key)) return -1;
const node = this.map.get(key);
this._remove(node); this._addFront(node);
return node.val;
}
put(key, val) {
if (this.map.has(key)) {
const node = this.map.get(key);
node.val = val;
this._remove(node); this._addFront(node);
return;
}
const node = { key, val, prev: null, next: null };
this.map.set(key, node);
this._addFront(node);
if (this.map.size > this.cap) {
const lru = this.tail.prev;
this._remove(lru);
this.map.delete(lru.key);
}
}
}Tradeoff: O(1) on every op. Dummy head/tail avoid the 'is this the only node' edge case. The DLL allows O(1) remove from any position.
Vercel-specific tips
Vercel grades the DLL + hash-map architecture. They may also accept JavaScript's built-in Map (which preserves insertion order), allowing a 10-line solution — mention this as the production-realistic answer. Bonus signal: noting the eviction edge case where the same key is updated (don't evict on existing-key update).
Common mistakes
- Using only a Map without re-inserting on access — order doesn't reflect recency.
- Evicting on update instead of insertion — wrong count after key collision.
- Storing key only in map (not in node) — can't delete from map on eviction.
Follow-up questions
An interviewer at Vercel may pivot to one of these next:
- LFU Cache (LC 460, hard) — least-frequently-used.
- TTL cache — time-based expiration.
- Concurrent LRU — same shape with locking.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Map alone (insertion-order-preserving)?
JavaScript's Map iterates in insertion order. On get: delete and re-set to bump to the end. On put: same, with eviction = delete the first key. Production-realistic in 10 lines. Mention it but be ready to do the DLL version on demand.
Why DLL not singly-linked?
O(1) removal requires the predecessor pointer. Singly-linked needs O(n) to find it (unless paired with a per-node parent pointer).
Practice these live with InterviewChamp.AI
Drill LRU Cache and other Vercel interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →