InterviewPrepKit

Home / Coding / Algorithm & Data Structure / Linked List

LRU Cache

medium Original ↗ 00:00

Problem

Design a data structure that behaves like a fixed-size cache with a Least Recently Used (LRU) eviction policy. It is created with a positive capacity and supports two operations:

  • get(key) — return the value stored for key, or -1 if key is not present. A successful get counts as using the key.
  • put(key, value) — insert or overwrite the value for key. Inserting or overwriting also counts as using the key. If adding a new key would push the number of stored entries above capacity, first evict the key that was used least recently.

Both operations must run in O(1) average time.

“Least recently used” means: among all keys currently in the cache, the one whose most recent get/put happened longest ago.

Examples

Example 1

LRUCache cache = new LRUCache(2)
put(1, 1)      // cache = {1=1}
put(2, 2)      // cache = {1=1, 2=2}
get(1)   -> 1  // 1 is now most-recently-used; order: 2 (old) ... 1 (new)
put(3, 3)      // capacity exceeded -> evict key 2; cache = {1=1, 3=3}
get(2)   -> -1 // 2 was evicted
put(4, 4)      // evict key 1; cache = {3=3, 4=4}
get(1)   -> -1
get(3)   -> 3
get(4)   -> 4

Example 2

LRUCache cache = new LRUCache(1)
put(1, 10)      // cache = {1=10}
put(2, 20)      // capacity 1 -> evict 1; cache = {2=20}
get(1)   -> -1
get(2)   -> 20

Overwriting an existing key never evicts, but it does refresh recency:

put(2, 99)      // cache = {2=99}, still size 1, no eviction
get(2)   -> 99

Constraints

  • 1 <= capacity <= 3000
  • 0 <= key <= 10^4, 0 <= value <= 10^5
  • Up to 2 * 10^5 calls total to get and put.
  • Every get and put must be O(1) on average — this rules out scanning the cache to find the least-recently-used entry.

Think about it first

Hint 1 You need two things fast: look up a key's value in O(1), and know the ordering from most- to least-recently-used so you can evict the right entry. A single array or dict alone gives you one but not the other.
Hint 2 Combine a hash map (key → node) with a doubly linked list that keeps nodes ordered by recency: most-recently-used at one end, least-recently-used at the other. Moving a node to the "recent" end and popping from the "old" end are both O(1) when you have direct node pointers.
Hint 3 Use sentinel `head` and `tail` nodes so you never special-case an empty list. On `get`: unlink the node and re-insert it next to `head`. On `put`: if the key exists, update and move to front; otherwise create a node, insert at front, and if over capacity remove the node before `tail` and delete its key from the map. Python's `collections.OrderedDict` (or a plain dict, which preserves insertion order) can do all of this for you.

Write your solution, then hit Run tests to check it — or get a mock grade from the AI coach.

The coach remembers this session — revise your code and ask again, and it grades your progress. It gives hints, not the answer.
Report a bug