← Uber Interview Insights

Uber·Machine Learning Engineer·Technical Phone Screen·Senior

SeniorPrefer not to say
May 2026

Summary

Went through a technical phone screen for an ML Engineer role at Uber and got hit with N-Queens. Classic backtracking problem but the follow-up questions about complexity and the counting variant kept things interesting longer than I expected.

Questions Asked (3)

Q1

Implement a solution to the N-Queens problem: place N queens on an N×N chessboard so no two queens share a row, column, or diagonal, and return all valid board configurations.

Algorithms & Data Structures
Author's notes

Went with row-by-row backtracking which felt right.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Use backtracking to place queens row by row, maintaining sets for columns and diagonals to ensure O(1) validity checks. At each row, try all columns, recurse, and backtrack; when row equals N, record the board configuration.

Pro tip: Mention that for large N, the number of solutions grows rapidly, so returning all configurations is only feasible for small N; in practice, you might return the count or use a generator. Also, note that symmetry can be exploited to reduce search space by half.

1. Clarify requirements and constraints

Confirm the expected output format (list of board configurations as strings or lists) and discuss time/space complexity. Ask if N is small enough to return all solutions.

2. Design backtracking algorithm

Use a recursive function that places a queen in the current row, iterating over columns. Maintain sets for occupied columns, diagonals (row+col), and anti-diagonals (row-col) to check validity in O(1).

3. Implement and handle base case

When row equals N, convert the current placement (e.g., an array of column indices) into the required board representation and add to results. Otherwise, recurse to the next row.

4. Optimize and analyze complexity

Discuss time complexity O(N!) and space O(N) for recursion and sets. Mention pruning and symmetry reduction as potential optimizations.

5. Test and validate

Walk through a small example (e.g., N=4) to verify correctness. Discuss edge cases like N=1 and N=2 (no solutions).

Key Points to Mention

  • Backtracking with pruning
  • Using sets for O(1) validity checks on columns and diagonals
  • Time complexity O(N!) and space O(N)
  • Board representation and conversion to output format
  • Symmetry reduction to halve search space
  • Handling edge cases (N=1, N=2, N=3)

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

Q2

What is the time complexity of your N-Queens backtracking solution, and how would you explain the upper bound?

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

This tripped me up more than the coding itself.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by stating the time complexity of your N-Queens backtracking solution, typically O(N!) or more precisely O(N! * N) depending on implementation. Then explain the upper bound by analyzing the branching factor at each row and the pruning due to column and diagonal conflicts. Emphasize that while the worst-case is factorial, pruning significantly reduces the actual runtime.

Pro tip: Acknowledge that the exact complexity is often stated as O(N!) but can be bounded by O(N! * N) if you check conflicts in O(N) time per placement; mention that with bitmasking or hash sets, conflict checks can be O(1), making the complexity closer to O(N!).

1. State the complexity

Clearly state the time complexity of your solution, e.g., O(N!) or O(N! * N), and note that space complexity is O(N) for the board and recursion stack.

2. Explain the branching factor

Describe how at each row you try up to N columns, but due to constraints, the number of valid positions decreases. The worst-case upper bound assumes minimal pruning, leading to N choices for the first row, N-1 for the second, etc., giving N!.

3. Account for conflict checking

If conflict checking takes O(N) time per placement (e.g., scanning columns and diagonals), multiply by N to get O(N! * N). If using O(1) checks (e.g., boolean arrays), it remains O(N!).

4. Discuss pruning and actual performance

Highlight that pruning drastically reduces the search space; the upper bound is loose. In practice, the algorithm explores far fewer states, but the worst-case remains factorial.

5. Relate to ML engineering context

Connect to ML engineering by noting that understanding complexity helps in optimizing search algorithms, which can be relevant for hyperparameter tuning or combinatorial optimization problems.

Key Points to Mention

  • Time complexity is O(N!) in the worst case, often expressed as O(N! * N) if conflict checking is O(N).
  • The upper bound comes from the number of permutations of N queens on an N x N board, with pruning reducing the actual number of nodes explored.
  • Space complexity is O(N) due to recursion depth and board storage.
  • Pruning via column and diagonal checks significantly reduces the effective branching factor.
  • Using bitmasks or hash sets can make conflict checks O(1), tightening the bound to O(N!).
  • The exact complexity is difficult to express in closed form; it's often approximated as O(N!).

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

Q3

How would you modify your solution if you only needed to count the number of valid configurations rather than return them all?

Algorithms & Data Structures
Author's notes

Pretty straightforward pivot once you have the backtracking logic.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying that counting valid configurations is a classic DP problem where you replace enumeration with counting. Explain how to define a DP state that tracks the number of ways to reach each configuration, then derive transitions and optimize space/time. Emphasize that the core logic remains the same but you avoid storing all solutions.

Pro tip: Mention that counting problems often allow for combinatorial shortcuts or matrix exponentiation when the state space is small, which can drastically reduce time complexity. Also, highlight that you should confirm whether the count needs to be modulo a large prime, as is common in competitive programming and ML pipeline constraints.

1. Clarify the problem and constraints

Confirm what defines a valid configuration, the input size, and whether the count should be modulo a number. This ensures you choose the right approach and complexity.

2. Define DP state and recurrence

Define dp[i][state] as the number of valid configurations up to position i ending in a given state. Derive the recurrence by summing over previous states that can transition to the current state.

3. Optimize space and time

If only the previous layer is needed, reduce space to O(states). Consider matrix exponentiation if transitions are linear and independent of i, or use prefix sums to speed up transitions.

4. Handle modulo and edge cases

Apply modulo at each addition to avoid overflow. Handle base cases (e.g., empty configuration) and ensure the final answer is the sum over all valid end states.

5. Analyze complexity and test

State the time and space complexity, and walk through a small example to verify the recurrence. Mention that the same DP can be adapted if the problem changes slightly.

Key Points to Mention

  • Dynamic programming with counting instead of enumeration
  • State definition and transition recurrence
  • Space optimization using rolling arrays
  • Modulo arithmetic to prevent overflow
  • Matrix exponentiation for linear recurrences
  • Time and space complexity analysis

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