Bird
Raised Fist0
Data Structures Theoryknowledge~6 mins

LRU cache design with hash map and doubly linked list in Data Structures Theory - Full Explanation

Choose your learning style10 modes available
Introduction
Imagine you have limited space to store your favorite books, but you want to keep the most recently read ones handy. The problem is deciding which book to remove when the space is full. This is the challenge that an LRU cache solves by remembering the order of use and quickly accessing stored items.
Explanation
Purpose of LRU Cache
An LRU (Least Recently Used) cache keeps track of the most recently accessed items and removes the least recently used ones when it reaches its capacity. This helps in managing limited storage efficiently by prioritizing recent data.
LRU cache removes the oldest unused items to make space for new ones.
Role of Hash Map
The hash map stores keys and points directly to nodes in the doubly linked list. This allows quick lookup of cache items in constant time, avoiding slow searches through the list.
Hash map enables fast access to cache items by key.
Role of Doubly Linked List
The doubly linked list keeps the order of items from most recently used at the front to least recently used at the back. When an item is accessed or added, it moves to the front. When the cache is full, the item at the back is removed.
Doubly linked list maintains usage order for quick updates.
How Both Structures Work Together
When accessing or adding an item, the hash map finds the node quickly, and the doubly linked list moves it to the front. If the cache is full, the list removes the last node, and the hash map deletes its key. This combination keeps operations fast and efficient.
Hash map and doubly linked list together provide fast access and update of cache items.
Real World Analogy

Imagine a desk with a small stack of papers you use often. When you read a paper, you put it on top of the stack. If the desk is full, you remove the paper at the bottom, which you haven't used recently. You also have a quick index that tells you where each paper is in the stack.

LRU Cache → The desk with limited space for papers
Hash Map → The quick index that tells where each paper is
Doubly Linked List → The stack of papers ordered by recent use
Removing least recently used → Taking the paper at the bottom of the stack off the desk
Diagram
Diagram
┌───────────────┐
│   Hash Map    │
│  Key → Node   │
└──────┬────────┘
       │
       ▼
┌─────────────────────────────┐
│ Doubly Linked List (Cache)  │
│ ┌─────┐ ┌─────┐ ┌─────┐     │
│ │ MRU │→│ ... │→│ LRU │     │
│ └─────┘ ←└─────┘ ←└─────┘     │
└─────────────────────────────┘
Diagram showing hash map pointing to nodes in a doubly linked list ordered from most recently used (MRU) to least recently used (LRU).
Key Facts
LRU Cache → A cache that removes the least recently used item when full.
Hash Map → A data structure that provides fast key-based access to values.
Doubly Linked List → A list where each node points to both its previous and next nodes.
Most Recently Used (MRU) → The item accessed or added most recently in the cache.
Least Recently Used (LRU) → The item that has not been accessed for the longest time in the cache.
Code Example
Data Structures Theory
class Node:
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None

class LRUCache:
    def __init__(self, capacity):
        self.capacity = capacity
        self.cache = {}  # key -> node
        self.head = Node(0, 0)  # dummy head
        self.tail = Node(0, 0)  # dummy tail
        self.head.next = self.tail
        self.tail.prev = self.head

    def _remove(self, node):
        prev = node.prev
        nxt = node.next
        prev.next = nxt
        nxt.prev = prev

    def _add(self, node):
        node.prev = self.head
        node.next = self.head.next
        self.head.next.prev = node
        self.head.next = node

    def get(self, key):
        if key in self.cache:
            node = self.cache[key]
            self._remove(node)
            self._add(node)
            return node.value
        return -1

    def put(self, key, value):
        if key in self.cache:
            self._remove(self.cache[key])
        node = Node(key, value)
        self._add(node)
        self.cache[key] = node
        if len(self.cache) > self.capacity:
            lru = self.tail.prev
            self._remove(lru)
            del self.cache[lru.key]
OutputSuccess
Common Confusions
Believing a simple list alone can provide fast access and update for LRU cache.
Believing a simple list alone can provide fast access and update for LRU cache. A simple list requires searching through all items, which is slow; combining a hash map with a doubly linked list allows both fast lookup and quick updates.
Thinking the hash map stores the order of usage.
Thinking the hash map stores the order of usage. The hash map only stores keys and pointers; the doubly linked list maintains the order of usage.
Summary
An LRU cache efficiently manages limited storage by removing the least recently used items first.
A hash map provides fast access to cache items by key, while a doubly linked list maintains the order of usage.
Together, these structures allow quick updates and lookups, keeping the cache fast and organized.

Practice

(1/5)
1. What is the main purpose of using a doubly linked list in an LRU cache design?
easy
A. To hash keys for constant time access
B. To store key-value pairs for fast lookup
C. To sort items by their values
D. To keep track of the order of item usage for quick updates

Solution

  1. Step 1: Understand the role of doubly linked list in LRU cache

    The doubly linked list maintains the order of items from most recently used to least recently used.
  2. Step 2: Explain why order tracking is important

    This order allows quick removal of the least recently used item when the cache is full.
  3. Final Answer:

    To keep track of the order of item usage for quick updates -> Option D
  4. Quick Check:

    Doubly linked list = usage order tracking [OK]
Hint: Doubly linked list tracks usage order in LRU cache [OK]
Common Mistakes:
  • Confusing hash map role with doubly linked list
  • Thinking doubly linked list stores key-value pairs
  • Assuming it sorts items by value
2. Which of the following correctly describes the time complexity of the get operation in an LRU cache implemented with a hash map and doubly linked list?
easy
A. O(n), where n is the number of items in the cache
B. O(1), constant time
C. O(log n), due to sorting
D. O(n^2), because of list traversal

Solution

  1. Step 1: Analyze the get operation components

    The hash map provides direct access to the node in constant time.
  2. Step 2: Consider the doubly linked list update

    Moving the accessed node to the front is done in constant time using pointers.
  3. Final Answer:

    O(1), constant time -> Option B
  4. Quick Check:

    Hash map + doubly linked list = O(1) get [OK]
Hint: Hash map lookup + list update = O(1) get [OK]
Common Mistakes:
  • Assuming list traversal causes O(n) time
  • Confusing sorting with LRU operations
  • Thinking get requires scanning all items
3. Consider an LRU cache with capacity 2. After these operations: put(1, 1), put(2, 2), get(1), put(3, 3), what will get(2) return?
medium
A. 2
B. 1
C. -1
D. 3

Solution

  1. Step 1: Track cache state after each operation

    After put(1,1) and put(2,2), cache has keys 1 and 2. get(1) makes key 1 most recently used.
  2. Step 2: Insert put(3,3) and evict least recently used

    Key 2 is least recently used and gets evicted. Cache now has keys 1 and 3.
  3. Step 3: Check get(2) result

    Key 2 was evicted, so get(2) returns -1.
  4. Final Answer:

    -1 -> Option C
  5. Quick Check:

    Evicted key 2, so get(2) = -1 [OK]
Hint: Evicted least used key returns -1 on get [OK]
Common Mistakes:
  • Forgetting eviction after capacity reached
  • Assuming get updates usage but doesn't evict
  • Returning wrong value for evicted key
4. In an LRU cache implementation, a developer notices that the cache never evicts any items even after exceeding capacity. What is the most likely cause?
medium
A. The eviction logic is missing or not triggered when capacity is exceeded
B. The doubly linked list is not updated to move recently used items to front
C. The hash map is not updated when items are accessed
D. The cache capacity is set to zero

Solution

  1. Step 1: Understand eviction role in LRU cache

    Eviction removes the least recently used item when capacity is exceeded.
  2. Step 2: Identify why eviction might not happen

    If eviction logic is missing or not triggered, items will never be removed despite capacity limits.
  3. Final Answer:

    The eviction logic is missing or not triggered when capacity is exceeded -> Option A
  4. Quick Check:

    Missing eviction = no item removal [OK]
Hint: Eviction missing means cache never removes items [OK]
Common Mistakes:
  • Blaming hash map updates for eviction issues
  • Ignoring eviction step in put operation
  • Assuming capacity zero means no eviction
5. You want to extend an LRU cache to also support a peekLeastUsed() operation that returns the least recently used key without removing it. Which data structure property allows this operation to be efficient?
hard
A. The tail pointer of the doubly linked list points to the least recently used item
B. The hash map stores keys in sorted order
C. The doubly linked list is singly linked for fast traversal
D. The cache uses a priority queue to track usage

Solution

  1. Step 1: Identify how least recently used item is tracked

    The doubly linked list keeps most recently used at head and least recently used at tail.
  2. Step 2: Explain how to access least used without removal

    Using the tail pointer, we can directly access the least recently used key efficiently.
  3. Final Answer:

    The tail pointer of the doubly linked list points to the least recently used item -> Option A
  4. Quick Check:

    Tail pointer = least recently used access [OK]
Hint: Tail of doubly linked list = least recently used key [OK]
Common Mistakes:
  • Assuming hash map stores sorted keys
  • Thinking singly linked list is used
  • Confusing priority queue with LRU structure
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard