Quick Overview

Build an LRU cache from a hash map and doubly linked list, supporting recency-changing reads, updates, and precise least-recently-used eviction at fixed capacity.

Build an LRU Cache with a Hash Map and Linked List

Company: Amazon

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: hard

Interview Round: HR Screen

## Problem Build an LRU cache backed by a hash map and a doubly linked list. Capacity is the number of entries. - `get(key)` returns the value or `-1`; a hit becomes most recently used. - `put(key, value)` inserts or updates; an existing key becomes most recently used. - Inserting a new key while full evicts exactly the least recently used entry. ### Portable Function Contract Implement `executeLru(capacity, operations)`. - `capacity` is an integer. - `operations` is a list of string rows. - A put row has exactly three fields: `["put", keyText, valueText]`. - A get row has exactly two fields: `["get", keyText]`. - `keyText` and `valueText` are canonical signed 64-bit decimal integers: `"0"`, a nonzero digit followed by digits, or `"-"` followed by a nonzero digit and then zero or more digits. They contain no leading zero, whitespace, or plus sign. Parse keys and values exactly as signed 64-bit integers. Return, in operation order, a list of canonical signed decimal strings for all `get` rows. A cache miss contributes `"-1"`. A hit contributes the stored value formatted canonically, so every signed 64-bit result remains exact through the JavaScript JSON transport. A stored value may also be `-1`; the returned string is the same in either case. All operation rows satisfy the shapes above. Their string encoding is part of the portable console interface; do not use a heterogeneous row whose first element is a string but whose other elements are language-specific numeric objects. ### Constraints & Assumptions - `1 <= capacity <= 100,000`. - At most `200,000` operations are supplied. - Keys and values are signed 64-bit integers encoded by the canonical strings above. - Average time per operation must be constant. - The returned list contains at most `200,000` canonical signed decimal strings. ### Clarifying Questions to Ask - Does `put` on an existing key trigger eviction? No; update and promote that entry. - Does a failed `get` affect recency? No. - Is the capacity measured by entry count? Yes. - Why are keys and values strings inside operation rows? A uniform string-row shape maps directly to all four console languages while preserving the exact integer values. - How should numeric strings be interpreted? Parse them as signed decimal 64-bit integers before applying the cache operation. ```hint One node must have one owner The map should point to the exact linked-list node. Moving or deleting that node must not leave another copy behind. ``` ```hint Isolate list operations Helpers for detach, attach-as-most-recent, and evict-least-recent make every public operation a short composition of correct primitives. ``` ### Example ```text capacity = 2 operations = [ ["put","1","10"], ["put","2","20"], ["get","1"], ["put","3","30"], ["get","2"], ["get","3"] ] result = ["10","-1","30"] ``` ### Evaluation Focus - Parses the uniform string rows into exact signed 64-bit keys and values and formats every get result canonically. - Promotes hits and updates to the most-recent position. - Deletes evicted nodes from both structures. - Handles capacity one, misses, negative keys and values, and repeated updates. - Uses `O(capacity)` space and average `O(1)` operations. ### Extensions to Discuss 1. How would a least-frequently-used policy change the data structures? 2. Where would locks be placed for a thread-safe implementation? 3. How would you add per-entry expiration?

Overview: Build an LRU cache from a hash map and doubly linked list, supporting recency-changing reads, updates, and precise least-recently-used eviction at fixed capacity.

Read the full Amazon Software Engineer interview experience this question came from

Process string-encoded signed 64-bit get and put operations in a fixed-capacity LRU cache. Return canonical decimal strings for gets, promoting hits and updates and evicting exactly the least recently used entry on an overflowing insertion.

Constraints

  • 1 <= capacity <= 100000.
  • At most 200000 exact-shape get or put rows are supplied.
  • Keys and values are canonical signed 64-bit decimal strings.
  • Return one canonical decimal string per get operation.

Examples

Input: (2, [['put', '1', '10'], ['put', '2', '20'], ['get', '1'], ['put', '3', '30'], ['get', '2'], ['get', '3']])

Expected Output: ['10', '-1', '30']

Explanation: Public sample 1.

Input: (1, [['put', '-7', '-1'], ['get', '-7'], ['put', '8', '9'], ['get', '-7'], ['get', '8']])

Expected Output: ['-1', '-1', '9']

Explanation: Public sample 2.

Hints

  1. Keep exactly one linked-list node per cached key.
  2. Detach and attach helpers make promotion and eviction symmetric.

Loading coding console...