Implement LRU Cache

O(1) get and put — hash map keyed to a doubly-linked-list node, splice node to the front on access, evict the tail on overflow.

Medium
Time O(1) per op Space O(capacity)
LeetCode
3 min read
design hash-map linked-list lru

Problem#

Build an LRU cache supporting get(key) and put(key, value) in O(1). On overflow, evict the least-recently-used entry. get and put both count as “uses”.

Examples#

  • cap=2; put(1,1); put(2,2); get(1)1, then put(3,3) evicts key 2.
  • get(2)-1 after the eviction.

Constraints#

  • 1 <= capacity <= 3000, up to 2 * 10^5 calls.

Approach#

Doubly linked list ordered most-recent → least-recent, plus a hash map from key to list iterator. Every access splices the node to the front. Overflow trims the tail.

Solution#

LRU Cache
class LRUCache {
int cap;
list<pair<int,int>> dll; // {key, val}, front = MRU
unordered_map<int, list<pair<int,int>>::iterator> mp;
public:
LRUCache(int capacity) : cap(capacity) {}
int get(int key) {
auto it = mp.find(key);
if (it == mp.end()) return -1;
dll.splice(dll.begin(), dll, it->second);
return it->second->second;
}
void put(int key, int value) {
auto it = mp.find(key);
if (it != mp.end()) {
it->second->second = value;
dll.splice(dll.begin(), dll, it->second);
return;
}
if ((int)dll.size() == cap) {
mp.erase(dll.back().first);
dll.pop_back();
}
dll.push_front({key, value});
mp[key] = dll.begin();
}
};

Editorial#

The key trick is list::splice, which re-links a node to a new position in O(1) without invalidating iterators — so the stored map iterator stays valid forever. The list itself encodes recency order; the map gives O(1) lookup.

Complexity#

  • Time: O(1) get/put.
  • Space: O(capacity).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.