Implement Expiring LRU Cache
Company: Bytedance
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: hard
Interview Round: Technical Screen
Quick Answer: This question evaluates skill in designing and implementing efficient in-memory caching data structures, testing understanding of LRU eviction, per-entry TTL expiration, and the use of hash maps and linked lists for O(1) operations.
Constraints
- 1 <= capacity <= 10^5
- 1 <= len(operations) <= 2 * 10^5
- 0 <= key, value, now <= 10^9
- 1 <= ttl <= 10^9
- The `now` values in `operations` are non-decreasing
Examples
Input: (2, [('put', 1, 10, 5, 0), ('put', 2, 20, 5, 1), ('get', 1, 2), ('put', 3, 30, 5, 3), ('get', 2, 4), ('get', 1, 5), ('get', 3, 7)])
Expected Output: [10, -1, -1, 30]
Explanation: Key 1 is read before it expires, making it most recently used. Inserting key 3 evicts key 2 as the LRU non-expired key. At time 5, key 1 expires exactly then, so it returns -1.
Input: (2, [('put', 1, 100, 2, 0), ('put', 1, 111, 5, 1), ('get', 1, 2), ('put', 2, 200, 10, 2), ('put', 1, 123, 1, 6), ('get', 1, 6), ('get', 2, 6), ('get', 1, 7)])
Expected Output: [111, 123, 200, -1]
Explanation: The first update to key 1 happens before expiration, so it refreshes value and TTL. At time 6, the old key 1 has already expired, so that put acts like a fresh insertion. At time 7, the new version expires exactly then.
Hints
- For the LRU behavior, the standard approach is a hash map for O(1) key lookup plus a doubly linked list for O(1) recency updates.
- Expiration can happen even for keys you do not directly access. Consider an additional structure ordered by expiration time and use lazy deletion to discard stale records.