← Bytedance Interview Insights
I went with the classic hashmap plus doubly linked list combo and felt pretty good about the get and put logic.
Start by clarifying requirements (capacity, TTL semantics, concurrency level), then propose a hash map + doubly linked list for O(1) LRU operations, augmented with TTL metadata and a cleanup strategy. Discuss trade-offs between lazy and active expiration, and explain concurrency approaches like sharding or fine-grained locking.
Pro tip: Emphasize that TTL and LRU are orthogonal concerns: TTL determines eligibility for eviction, while LRU determines order. Propose a hybrid cleanup (lazy on access + periodic sweep) to balance memory and latency, and mention that real systems often use approximate LRU (e.g., sampling) for scalability.
Ask about expected capacity, read/write ratio, TTL granularity, concurrency needs, and whether strict LRU or approximate is acceptable. This shapes data structure and locking choices.
Use a hash map for O(1) key lookup and a doubly linked list for O(1) recency updates. Store TTL expiration timestamp in each node. Explain how get and put update recency and handle capacity.
On put, if capacity exceeded, evict least recently used entry. For TTL, check expiration on access (lazy) and optionally run a background thread to periodically remove expired entries. Discuss trade-offs.
State that get, put, and evict are O(1) average time. Space is O(capacity). Mention that periodic cleanup adds O(n) per sweep but amortized cost is low.
Propose thread-safe design: either a single lock (simple but contended), fine-grained locks per bucket/shard, or lock-free with atomic operations. Discuss read-write locks and sharding to reduce contention.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.