A-043● Day 432026.06.18mediumleetcode #146neetcode150
LRU Cache
#hash-table#linked-list#design#doubly-linked-list
01
Problem
· problemDesign a data structure that follows the constraints of a Least Recently Used (LRU) cache. Implement the LRUCache class: - LRUCache(int capacity): Initialize the LRU cache with positive size capacity. - int get(int key): Return the value of the key if the key exists, otherwise return -1. - void put(int key, int value): Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key. The functions get and put must each run in O(1) average time complexity.
constraints
- · 1 ≤ capacity ≤ 3000
- · 0 ≤ key ≤ 10^4
- · 0 ≤ value ≤ 10^5
- · At most 2 × 10^5 calls to get() and put()
- · Both get() and put() must achieve O(1) time complexity
// paraphrased summary — see source for full text
examples
02
Pre-solve
· pre-solve● 1list shown→● 2select→● 3reveal
- ☐Why must the get() operation update the cache recency order?
- ☐What is the purpose of using sentinel nodes (left, right) in the doubly-linked list?
- ☐Why combine a hash map with a doubly-linked list instead of using just one?
- ☐Could we use only timestamps/counters to achieve O(1) performance for both operations?
- ☐What happens if we update an existing key's value in put() without moving it to the right?
check the items you would ask, then press confirm
// session-only state — refresh resets (repeatable practice)
03
Logic Structure
· logic● 1slots shown→● 2pick per slot→● 3reveal
// pick one code line per slot to assemble the algorithm flow. no typing — just the logic skeleton.
step 1· Initialize cache hash map
○
self.cache = {} # map key to node○
self.cache = []
○
self.cache = None
○
self.cache = set()
step 2· Create sentinel nodes for list boundaries
○
self.left, self.right = Node(0, 0), Node(0, 0)
○
self.left = self.right = None
○
self.left = Node(0, 0); self.right = self.left
step 3· Disconnect node by updating both directional links
○
prev.next, nxt.prev = nxt, prev
○
prev.next = nxt
○
node.prev = None; node.next = None
○
nxt.prev = prev
step 4· Connect node at right end (most recent position)
○
node.next, node.prev = nxt, prev
○
node.next, node.prev = self.left, self.left.next
○
node.prev = self.right; node.next = None
○
prev.next = node
step 5· Get: Remove node to update recency
○
self.remove(self.cache[key])
○
return self.cache[key].val
○
self.insert(self.cache[key]); return self.cache[key].val
step 6· Put: Identify LRU node as left.next
○
lru = self.left.next
○
lru = self.right.prev
○
lru = self.cache[min(self.cache.keys())]
○
lru = list(self.cache.values())[0]
pick one option per slot
// format: slot — recursive / DP patterns use ordering / state-first formats. ADR-08 follow-up.
04
Solve · Trace
· solvemental dry-run cases
// walk each case in your head; expand the worked example below if stuck.
case 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]
// UI does not walk-through — you do the dry-run mentally. Expand the worked example if stuck.