Implement an LRU cache
Company: TikTok
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: easy
Interview Round: Technical Screen
Quick Answer: This question evaluates understanding of cache design and eviction policies (LRU), along with competency in selecting and reasoning about data structures and complexity to support efficient get and put operations under capacity constraints.
Constraints
- 1 <= capacity
- 0 <= number of operations
- Keys and values are integers
- get on a missing key returns -1
- put that updates an existing key marks it most recently used and does NOT evict
- Both get and put must be O(1) average time
Examples
Input: (2, [['put', 1, 10], ['put', 2, 20], ['get', 1], ['put', 3, 30], ['get', 2], ['get', 3], ['get', 1]])
Expected Output: [10, -1, 30, 10]
Explanation: After put(1,10),put(2,20): {1,2}. get(1)=10 makes 1 MRU. put(3,30) evicts LRU key 2 -> {1,3}. get(2)=-1 (evicted), get(3)=30, get(1)=10.
Input: (2, [['put', 1, 1], ['put', 2, 2], ['get', 1], ['put', 3, 3], ['get', 2], ['put', 4, 4], ['get', 1], ['get', 3], ['get', 4]])
Expected Output: [1, -1, -1, 3, 4]
Explanation: Classic LeetCode trace: get(1)=1; put(3) evicts 2 so get(2)=-1; put(4) evicts 1 so get(1)=-1; get(3)=3; get(4)=4.
Input: (1, [['put', 2, 1], ['get', 2], ['put', 3, 2], ['get', 2], ['get', 3]])
Expected Output: [1, -1, 2]
Explanation: Capacity 1: put(2,1); get(2)=1; put(3,2) evicts 2; get(2)=-1; get(3)=2.
Input: (2, [['put', 1, 10], ['put', 1, 20], ['get', 1]])
Expected Output: [20]
Explanation: Updating an existing key overwrites the value and marks it MRU without evicting; get(1)=20.
Input: (2, [['get', 0]])
Expected Output: [-1]
Explanation: Edge case: get on an empty cache returns -1.
Input: (3, [['put', 1, 1], ['put', 2, 2], ['put', 3, 3], ['get', 1], ['put', 4, 4], ['get', 2], ['get', 1], ['get', 3], ['get', 4]])
Expected Output: [1, -1, 1, 3, 4]
Explanation: Cache fills to {1,2,3}; get(1) makes 1 MRU; put(4) evicts LRU key 2; get(2)=-1, get(1)=1, get(3)=3, get(4)=4.
Hints
- Combine a hash map (key -> node) with a doubly linked list ordered from least to most recently used. The map gives O(1) lookup; the list gives O(1) reordering and eviction.
- On get/put of an existing key, move that node to the most-recently-used end. On a brand-new put, append it and, if size exceeds capacity, remove the node at the least-recently-used end.
- An ordered hash map (Python OrderedDict / collections, Java LinkedHashMap, JS Map) gives the same behavior: move_to_end on access, popitem(last=False) to evict the oldest.