← Back to DSA map
Linked List & Design

LRU Cache

A cache of fixed size that throws out the key nobody has touched for longest - and does it in a constant number of steps.

Medium

Problem

Design a data structure that follows the Least Recently Used (LRU) policy. Implement LRUCache(capacity), get(key) which returns the value or -1, and put(key, value) which inserts or updates and evicts the least recently used key when over capacity.

  • get and put must each take a constant number of steps, no matter how big the cache is.
  • Reading a key with get counts as using it.
  • Updating an existing key counts as using it.

Examples

Input: capacity 2: put(1,1), put(2,2), get(1), put(3,3), get(2), put(4,4), get(1), get(3), get(4)
Output: 1, -1, -1, 3, 4
put(3,3) evicts key 2, which was used least recently; put(4,4) then evicts key 1.

Approach

Time O(1) get / putSpace O(capacity)
  1. A map finds a key instantly but knows nothing about order. A doubly linked list - a chain where each node points both forwards and backwards - can move an item in one step but cannot find it. Use both together.
  2. The map stores key -> the node holding it. The chain runs from most recently used at the front to least recently used at the back. Two empty placeholder nodes sit at each end so you never have to special-case the first or last item.
  3. get: if the key is there, take its node out of the chain, put it back at the front, and return its value.
  4. put: update and move to front if the key exists; otherwise add a new node at the front, and if the size exceeds capacity, remove the node before the tail and delete its key from the map.

Brute force: Keep an array in recency order. Finding a key and moving it means walking the array each time.

Common mistakes

  • Forgetting to move a key to the front on get, so reads do not count as use.
  • Removing the list node but not the map entry, or the other way round.
  • The node must store its key, or you cannot delete the evicted entry from the map.

Step through it

Pick an input and play the algorithm step by step. The highlighted line in the code follows each step, and you can edit the code to experiment.

LRU CACHE`get` counts as using a key, so it moves to the most-recently-used end.
Operations
1.put(1, 1)
2.put(2, 2)
3.get(1)
4.put(3, 3)
5.get(2)
6.put(4, 4)
7.get(1)
8.get(3)
9.get(4)
Solution · JS
Chain of nodes · most recently used → least recently used
Doubly linked list
HEAD
→←
TAIL
op —
size 0/2
return —
MAPempty
Cap
2
Size
0
Key
—
Return
—
0 / 0
1×
Execution log
steps appear here…

Solution

The same approach in JavaScript, Python, and Java. Each is a complete program that prints the examples above - JavaScript runs here, so edit it and try your own input.

Edit and run it here

JavaScript solution

Loading...

Output

Run code to see output...

Comments

Sign in to leave a comment. Your name and photo come from Google; nothing else is shared.

Loading comments...