17. LRU Cache
mediumAsked at IntuitDesign an LRU (least-recently-used) cache with O(1) get and put. Intuit asks this to test data-structure composition (hash + doubly-linked list) and reframes it as 'cache the last N tax-form lookups' for TurboTax candidates.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Intuit loops.
- Glassdoor (2026-Q1)— Intuit SWE II onsite — system-design-flavored coding round.
- LeetCode Discuss (2025-10)— TurboTax engineer cited LRU as the standard 45-min coding round.
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 return -1; void put(int key, int value) updates the value if the key exists, otherwise add 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(2); put(1,1); put(2,2); get(1); put(3,3); get(2); put(4,4); get(1); get(3); get(4);[1,-1,-1,3,4]Explanation: put(3,3) evicts key 2; put(4,4) evicts key 1.
Approaches
1. Map with insertion-order iteration
Use JS Map (preserves insertion order). On get, delete and re-set to refresh recency. On put past capacity, delete the first key.
- Time
- O(1) amortized
- Space
- O(capacity)
class LRUCache {
constructor(capacity) { this.cap = capacity; this.map = new Map(); }
get(key) {
if (!this.map.has(key)) return -1;
const v = this.map.get(key);
this.map.delete(key);
this.map.set(key, v);
return v;
}
put(key, value) {
if (this.map.has(key)) this.map.delete(key);
else if (this.map.size >= this.cap) this.map.delete(this.map.keys().next().value);
this.map.set(key, value);
}
}Tradeoff: Cleanest in JS — leans on Map's documented insertion-order behavior. Interviewer may want the doubly-linked-list version explicitly.
2. Hash + doubly-linked list (canonical)
Doubly-linked list keeps MRU at head, LRU at tail. Hash map points keys to list nodes for O(1) lookup. Get: lookup + move-to-head. Put: lookup-and-update or insert-at-head + evict tail.
- Time
- O(1)
- Space
- O(capacity)
class Node { constructor(k,v){ this.k=k; this.v=v; this.prev=null; this.next=null; } }
class LRUCache {
constructor(capacity){
this.cap = capacity;
this.map = new Map();
this.head = new Node(); this.tail = new Node();
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 n = this.map.get(key);
this._remove(n); this._addFront(n);
return n.v;
}
put(key,value){
if(this.map.has(key)){
const n = this.map.get(key); n.v = value;
this._remove(n); this._addFront(n);
return;
}
if(this.map.size >= this.cap){
const lru = this.tail.prev;
this._remove(lru);
this.map.delete(lru.k);
}
const n = new Node(key,value);
this._addFront(n);
this.map.set(key, n);
}
}Tradeoff: Truly O(1) per operation. Sentinel head/tail nodes eliminate null checks. This is what most interviewers want to see.
Intuit-specific tips
Intuit interviewers will ask whether you'd use the Map shortcut or write the doubly-linked list explicitly — pick the DLL version in a 45-min round to demonstrate the data-structure composition. They grade for sentinel nodes (head/tail) eliminating edge cases. Bonus signal: discuss eviction policy variants (LFU = LC 460, TinyLFU, ARC) and where each wins.
Common mistakes
- Forgetting to update the recency on get — the cache devolves to FIFO.
- Using a singly-linked list and getting O(n) remove operations.
- Forgetting to delete the evicted key from the hash map — memory leak.
Follow-up questions
An interviewer at Intuit may pivot to one of these next:
- LFU Cache — evict by frequency, not recency (LC 460).
- Make the cache thread-safe.
- Add a TTL to each entry and evict on expiry.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why a doubly-linked list and not singly?
Singly-linked removal is O(n) because you need the predecessor. Doubly-linked gives O(1) removal with a direct pointer to the node from the hash map.
Can I use JS Map's insertion order in a real interview?
Yes for a phone screen, but for an onsite, write the DLL explicitly. Interviewers want to see you compose primitives, not lean on language-specific behavior.
Practice these live with InterviewChamp.AI
Drill LRU Cache and other Intuit interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →