DSAMaster Logo
DSAMaster
System Design• 25 June 2026• 10 min read

LRU Cache Design: Hash Map, Linked List, and Worked Example

Design an LRU cache with a hash map and doubly linked list. Follow eviction and update examples, understand expected O(1) operations, and compare C++, Java, Python, and JavaScript implementations.

D
Written by DSAMaster Team
DSAMaster Editorial

1. Introduction to LRU Cache Design

This guide develops one data-structure design problem: a least recently used (LRU) cache. It is a useful starting point for low-level design, but it is not a complete system-design curriculum. The implementations below store integer keys and values and return -1 when a key is absent. Capacity is assumed to be non-negative.


2. Core LLD Questions

Q1. Design LRU Cache

A cache has a fixed number of entries. get(key) returns the stored value and marks that entry as recently used. put(key, value) inserts or updates an entry and also marks it as recently used. If a new insertion exceeds capacity, evict the entry that has gone longest without a successful read or write. A missing read must not change the order.

Why combine two data structures?

A hash map finds the node for a key in expected constant time, but it does not by itself support moving an arbitrary entry within a recency ordering. A doubly linked list supports removing a known node and inserting it at the front without walking the list. Combining them gives each structure one job: lookup in the map, ordering in the list.

The head and tail are sentinel nodes, not cache entries. The node after head is the most recently used; the node before tail is the least recently used. Every map entry points to exactly one linked node. Removing a node must reconnect both neighbours. Eviction must also remove its map entry; otherwise a future lookup could return stale data or, in C++, a freed pointer.

Worked example: capacity two

OperationResultOrder, newest first
put(1, 10)Insert key 11
put(2, 20)Insert key 22, 1
get(1)Returns 101, 2
put(3, 30)Evicts key 23, 1
get(2)Returns -13, 1
put(1, 15)Updates key 11, 3
put(4, 40)Evicts key 34, 1

Updating key 1 must not increase the number of entries. The C++ implementation reuses that node and moves it to the front, avoiding a leaked allocation. Its destructor releases all nodes, including the sentinels; copying is disabled because a shallow copy would otherwise share owning pointers.

Complexity and limits

Each operation changes a fixed number of list pointers and performs a few hash-map operations. Time is expected O(1), rather than a worst-case guarantee for every hash-table implementation. Space is O(capacity), plus the two sentinels. With capacity zero, every insertion is immediately evicted.

These examples are single-threaded, in-memory caches. They do not implement expiration, persistence, or coordination between servers. In a concurrent service, lookup and recency updates must be synchronized together. LRU is also vulnerable to scans: reading many distinct keys once can evict a frequently used working set. Those tradeoffs belong in a design discussion rather than being hidden behind an O(1) claim.

Implementation

javascript
class Node { constructor(key = 0, val = 0) { this.key = key; this.val = val; 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(node) { node.prev.next = node.next; node.next.prev = node.prev; } _add(node) { node.next = this.head.next; node.prev = this.head; this.head.next.prev = node; this.head.next = node; } get(key) { if (!this.map.has(key)) return -1; let node = this.map.get(key); this._remove(node); this._add(node); return node.val; } put(key, value) { if (this.map.has(key)) this._remove(this.map.get(key)); let node = new Node(key, value); this._add(node); this.map.set(key, node); if (this.map.size > this.cap) { let lru = this.tail.prev; this._remove(lru); this.map.delete(lru.key); } } }

Time Complexity: expected O(1) | Space Complexity: O(capacity)


3. Summary Table

SystemData StructureTimeSpace
LRU CacheHash Map + Doubly Linked ListO(1)O(capacity)

Explore more practice problems on DSAMaster's practice platform.