← Intuit Interview Insights

Intuit·Software Engineer·Technical Phone Screen·Intermediate

Intermediate
May 2026

Summary

Intuit SWE interview that went deep on caching. The LRU part felt manageable but the LFU follow-up is where things got real, and I don't think I handled the tie-breaking explanation as cleanly as I should have.

Questions Asked (2)

Q1

Design an in-memory LRU cache with capacity N that supports O(1) get and put operations. Walk through your data structure choices and analyze time and space complexity.

Algorithms & Data StructuresSystem DesignTechnical Trade-offs
Author's notes

Went with a hashmap plus a doubly linked list, which is the standard answer, and I knew it going in.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements (capacity N, O(1) get/put, eviction policy). Then propose a hash map combined with a doubly linked list to achieve O(1) operations, and walk through the implementation details, including edge cases. Finally, analyze time and space complexity and discuss potential optimizations or trade-offs.

Pro tip: Mention that using a doubly linked list allows O(1) removal and insertion, and that the hash map stores references to list nodes. Also, discuss thread-safety if the cache might be accessed concurrently, as Intuit values production-ready thinking.

1. Clarify Requirements

Confirm the capacity N, that get and put must be O(1), and the eviction policy (least recently used). Ask about concurrency requirements and whether null values are allowed.

2. Choose Data Structures

Propose a hash map (for O(1) key lookup) and a doubly linked list (for O(1) insertion/removal and maintaining recency order). Explain that the hash map maps keys to nodes in the list.

3. Detail Operations

Describe get: if key exists, move node to front (most recently used) and return value; else return -1. Describe put: if key exists, update value and move to front; else create new node, add to front, and if capacity exceeded, remove least recently used (tail) and delete from map.

4. Analyze Complexity

State that both get and put are O(1) time due to hash map and linked list operations. Space complexity is O(N) for storing up to N entries.

5. Discuss Edge Cases and Trade-offs

Mention handling of capacity 0 or 1, updating existing keys, and potential thread-safety (e.g., using locks or concurrent data structures). Optionally, compare with alternative implementations like using LinkedHashMap in Java.

Key Points to Mention

  • Hash map provides O(1) average-case lookup, but worst-case O(n) if collisions; mention that in practice it's O(1).
  • Doubly linked list allows O(1) removal and insertion at both ends, and moving a node to the front is O(1) if we have a reference to it.
  • The hash map stores key -> node reference, so we can quickly find and update the node's position in the list.
  • Eviction: when capacity is exceeded, remove the tail node (least recently used) and delete its key from the hash map.
  • Space complexity: O(N) for the map and list, where N is capacity.
  • Thread-safety: if needed, use synchronization or ConcurrentHashMap with a concurrent linked list, but note that it may impact performance.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Now modify your design to support an LFU cache with O(1) or amortized O(1) operations. How do you track and update frequencies on get and put, and how do you break ties using recency?

Algorithms & Data StructuresSystem DesignTechnical Trade-offs
Author's notes

This is where I started sweating.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the core data structures: a frequency map where each frequency points to a doubly linked list of nodes (LRU order), and a node-to-frequency mapping. Then describe how get and put update frequencies by moving nodes between lists, and how to find the minimum frequency in O(1) using a min_freq pointer. Finally, explain tie-breaking by maintaining recency order within each frequency list.

Pro tip: Mention that LFU with recency tie-breaking is essentially a combination of LFU and LRU, and that using a min_freq pointer avoids scanning for the least frequency. Also, note that amortized O(1) is achieved because each operation moves a node at most once.

1. Clarify requirements and constraints

Confirm that operations must be O(1) or amortized O(1), and that ties are broken by recency (LRU). Ask about cache size and whether frequencies can be updated on both get and put.

2. Design core data structures

Use a hash map for key-to-node lookup, a frequency map mapping frequency to a doubly linked list of nodes (ordered by recency), and maintain a min_freq variable. Each node stores key, value, freq, and pointers for the linked list.

3. Implement get operation

On get, if key exists, retrieve node, increment its frequency, move it from its current frequency list to the next frequency list (or create new), update min_freq if necessary, and return value. If not, return -1.

4. Implement put operation

On put, if key exists, update value and increment frequency similarly to get. If new, insert with frequency 1; if cache is full, evict the least frequently used node (from min_freq list, least recently used among them), then insert new node. Update min_freq to 1.

5. Explain tie-breaking and complexity

Within each frequency list, maintain recency order by adding new nodes at the head and moving accessed nodes to the head of the next frequency list. This ensures ties are broken by LRU. All operations are O(1) amortized because each node moves at most once per operation.

Key Points to Mention

  • Use of a frequency map (frequency -> doubly linked list) to group nodes by frequency.
  • Maintaining a min_freq pointer to achieve O(1) eviction of the least frequently used item.
  • Incrementing frequency on both get and put, and moving nodes between frequency lists.
  • Tie-breaking by recency: within the same frequency, the least recently used node is evicted first.
  • Amortized O(1) complexity: each operation involves a constant number of pointer updates and hash map lookups.
  • Handling edge cases: cache size 1, updating existing key, and evicting when full.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.