← Apple Interview Insights

Apple·Software Engineer·Onsite - Coding / Algorithms·Senior

SeniorPrefer not to say
Jul 2026

Summary

Apple coding round with four back-to-back algorithmic problems. The questions were meaty and covered a decent range, from in-place matrix manipulation to streaming data structures. Felt like a standard senior-level onsite gauntlet.

Questions Asked (4)

Q1

Given an n×n integer matrix representing an image, rotate it 90 degrees clockwise in place using only O(1) extra space. Justify the time and space complexity and walk through edge cases.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Classic problem but the O(1) constraint is where people trip up.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Use a two-step in-place transformation: first transpose the matrix (swap elements across the main diagonal), then reverse each row. This achieves the 90-degree clockwise rotation with O(1) extra space and O(n^2) time. Clearly explain the mapping of each element and justify why the space is constant.

Pro tip: Mention that the rotation can be done in a single pass by swapping four elements at a time in a cycle, but the transpose+reverse method is simpler and less error-prone. Also, note that the problem assumes a square matrix; for non-square, the approach differs.

1. Clarify the problem and constraints

Confirm that the matrix is n×n, rotation is 90 degrees clockwise, and it must be done in-place with O(1) extra space. Ask if n can be 0 or 1, and if the matrix is mutable.

2. Explain the transpose + reverse approach

Describe how transposing swaps matrix[i][j] with matrix[j][i] for i < j, then reversing each row yields the clockwise rotation. Walk through a small example (e.g., 3×3) to illustrate.

3. Analyze time and space complexity

State that transposing visits each element once (O(n^2)), and reversing rows also takes O(n^2), so overall time is O(n^2). Space is O(1) because only a temporary variable is used for swaps.

4. Discuss edge cases

Cover n=0 (empty matrix), n=1 (no change), and large n (performance). Also mention that the algorithm works for any integer values, including negatives.

5. Consider alternative in-place methods

Briefly mention the four-way swap cycle method, which rotates four elements at a time in a single pass, but note it's more complex to implement correctly.

Key Points to Mention

  • Transpose then reverse each row yields 90-degree clockwise rotation.
  • Time complexity: O(n^2) because each element is visited a constant number of times.
  • Space complexity: O(1) extra space, as only a few variables are used.
  • Edge cases: n=0, n=1, and large n; also handle non-square matrices if asked.
  • Alternative: four-way swap cycle for single-pass rotation, but more error-prone.
  • In-place means modifying the input matrix directly without allocating another matrix.

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

Q2

Design an in-memory LRU cache with a given capacity that supports get and put in O(1) average time. Describe your data structures, how you'd handle concurrent access, and how you'd add optional TTL expiration.

System DesignTechnical Trade-offsAlgorithms & Data Structures
Author's notes

The base LRU with a hashmap plus doubly linked list is something I could draw in my sleep, but the concurrency and TTL parts are where the conversation got interesting.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by outlining the core data structures: a hash map for O(1) lookups and a doubly linked list for O(1) eviction/insertion. Then discuss concurrency strategies (e.g., sharding, locks, or lock-free approaches) and finally explain how to integrate TTL using timestamps and lazy or active expiration.

Pro tip: Emphasize trade-offs: for example, sharding reduces lock contention but complicates global LRU ordering; TTL adds overhead but can be optimized with a min-heap or timing wheel. Apple values practical, scalable solutions that balance performance and complexity.

1. Clarify requirements and constraints

Ask about expected throughput, read/write ratio, consistency needs, and whether TTL is mandatory or optional. This shows you consider real-world usage before diving into design.

2. Design core data structures for O(1) operations

Explain using a hash map (key -> node) and a doubly linked list (nodes in access order). Describe how get moves a node to the front and put inserts/updates and evicts the tail when capacity is exceeded.

3. Address concurrent access

Discuss options: a single mutex (simple but contended), fine-grained locking (e.g., per-bucket locks with a global LRU list), or sharding the cache into independent segments. Mention trade-offs between simplicity and scalability.

4. Integrate TTL expiration

Propose storing an expiration timestamp in each node. For expiration, use lazy deletion on access and/or a background thread with a min-heap or timing wheel to proactively remove expired entries. Discuss overhead and trade-offs.

5. Summarize and discuss trade-offs

Recap the design, highlighting how it meets O(1) average time, handles concurrency, and supports TTL. Mention potential optimizations and limitations (e.g., memory overhead, lock contention).

Key Points to Mention

  • Hash map + doubly linked list for O(1) get/put and LRU eviction
  • Concurrency: mutex vs. sharding vs. lock-free (e.g., using atomic operations)
  • TTL implementation: timestamps, lazy expiration, and active expiration with a min-heap or timing wheel
  • Trade-offs: lock contention vs. complexity, memory overhead of TTL, and consistency vs. performance
  • Edge cases: capacity 0 or 1, concurrent eviction and insertion, clock skew for TTL
  • Real-world considerations: thread safety, scalability, and integration with existing systems

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

Q3

Build a data structure that supports adding numbers from a stream and querying the current median, with O(log n) insertion and O(1) median retrieval. Explain how you handle both odd and even element counts.

Algorithms & Data Structures
Author's notes

Two heaps.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Use two heaps: a max-heap for the lower half and a min-heap for the upper half, keeping their sizes balanced. Insertion involves adding to the appropriate heap and rebalancing, while median retrieval is O(1) by peeking at the heap tops. For odd total count, the median is the top of the larger heap; for even, it's the average of both tops.

Pro tip: Mention that this approach also works for streaming data with limited memory, and discuss how to handle duplicates and negative numbers gracefully.

1. Clarify requirements and constraints

Confirm that the data structure should support dynamic insertion and median queries, and discuss expected input size and data types.

2. Choose the two-heap approach

Explain that a max-heap stores the smaller half and a min-heap stores the larger half, maintaining size balance.

3. Detail insertion and rebalancing

Describe adding the new element to one heap based on comparison with the other heap's top, then rebalancing sizes so they differ by at most one.

4. Explain median retrieval for odd and even counts

For odd total, return the top of the larger heap; for even, return the average of the two heap tops.

5. Analyze complexity and edge cases

State that insertion is O(log n) due to heap operations, median retrieval is O(1), and discuss handling empty stream or single element.

Key Points to Mention

  • Two heaps: max-heap for lower half, min-heap for upper half
  • Balancing condition: sizes differ by at most 1
  • Insertion: add to appropriate heap, then rebalance
  • Median: O(1) by peeking at heap tops
  • Odd count: median is top of larger heap
  • Even count: median is average of both tops

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

Q4

Given a graph as adjacency lists, detect whether it contains a cycle. Provide a solution for directed graphs, explain how the approach differs for undirected graphs, and optionally return an example cycle if one exists.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

For directed graphs I went with DFS and a three-color visited set to distinguish nodes in the current recursion stack from fully processed ones.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the graph type (directed vs. undirected) and whether you need to return an example cycle. For directed graphs, use DFS with a recursion stack (or three-color marking) to detect back edges; for undirected graphs, use DFS with parent tracking or Union-Find, noting that each edge appears twice. If returning a cycle, maintain a parent map to reconstruct the path when a back edge is found.

Pro tip: Mention that for directed graphs, a simple visited set is insufficient—you must track nodes in the current recursion stack (or use colors) to distinguish cross edges from back edges. Also, note that Union-Find is often preferred for undirected graphs due to its near-linear time and simplicity, but DFS is needed if you must return the actual cycle.

1. Clarify requirements and constraints

Ask whether the graph is directed or undirected, if it may be disconnected, and whether you need to return an example cycle or just a boolean. This determines the algorithm and data structures.

2. Choose the right algorithm

For directed graphs, use DFS with a recursion stack (or three-color marking) to detect back edges. For undirected graphs, use DFS with parent tracking or Union-Find, being careful to ignore the edge back to the parent.

3. Implement cycle detection

Write the DFS (or Union-Find) code, handling disconnected components by iterating over all nodes. For directed graphs, maintain a 'visiting' set (or color array) and a 'visited' set; for undirected, pass the parent to avoid false positives.

4. Optionally reconstruct the cycle

If required, maintain a parent map during DFS. When a back edge is found, trace back from the current node to the ancestor using the parent map to build the cycle path.

5. Analyze complexity and trade-offs

State that both approaches run in O(V+E) time and O(V) space. Discuss trade-offs: DFS is simpler for directed graphs and can return a cycle; Union-Find is often faster for undirected graphs but doesn't easily return the cycle.

Key Points to Mention

  • Directed graphs require tracking the current recursion stack (or three colors) to detect back edges, while undirected graphs only need to avoid revisiting the immediate parent.
  • Union-Find (Disjoint Set Union) is an efficient alternative for undirected graphs, with near O(E α(V)) time, but it cannot easily return the actual cycle.
  • For directed graphs, a simple visited set is insufficient because it would flag cross edges as cycles; you must distinguish between nodes in the current path and those fully processed.
  • When returning a cycle, maintain a parent map during DFS and reconstruct the path from the current node back to the ancestor when a back edge is found.
  • Handle disconnected graphs by iterating over all vertices and starting a DFS from each unvisited node.
  • Time complexity is O(V+E) for DFS and O(E α(V)) for Union-Find; space complexity is O(V) for both.

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