← Uber Interview Insights

Uber·Data Scientist·Technical Phone Screen·Senior

Senior
Jun 2026

Summary

Uber data science interview that went deep into numerical methods, which I was not expecting at all. Two coding problems plus four follow-up theory questions, all in one session. Felt more like a computational math exam than a DS interview.

Questions Asked (6)

Q1

Implement a square root function using Newton's method in Python, without using any built-in sqrt or pow. It needs to handle the full float range including zero, very large values, and infinity, raise an error for negatives, use a numerically stable initial guess, and stop when the relative error is within a given tolerance or after 100 iterations.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

I had a rough start because I forgot about the overflow risk for large x.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying edge cases and constraints, then outline Newton's method with a stable initial guess and relative error stopping criterion. Write clean Python code with clear variable names and comments, and test with representative values including edge cases.

Pro tip: Mention that for very large numbers, a good initial guess is crucial to avoid overflow; using x/2 or a bit-shift-based estimate can help. Also, note that relative error is preferred over absolute error for floating-point comparisons.

1. Clarify requirements and edge cases

Confirm the expected behavior for zero, infinity, negative inputs, and very large/small numbers. Discuss tolerance and iteration limit.

2. Design the algorithm

Explain Newton's method formula: x_{n+1} = 0.5 * (x_n + n / x_n). Choose a stable initial guess, e.g., x0 = n if n >= 1 else 1, or use exponent manipulation.

3. Implement in Python

Write the function with proper error handling for negatives, special cases for 0 and infinity, and a loop with relative error check and iteration cap.

4. Test and validate

Test with values like 0, 1, 2, 1e300, float('inf'), and negative numbers. Verify accuracy and performance.

5. Discuss trade-offs and optimizations

Talk about convergence speed, numerical stability, and potential improvements like using math.frexp for initial guess.

Key Points to Mention

  • Newton's method iteration formula and quadratic convergence
  • Handling of special cases: zero, infinity, negative inputs
  • Choice of initial guess for numerical stability (e.g., using exponent bits or x/2)
  • Relative error stopping criterion: abs((x_new - x_old) / x_new) < tolerance
  • Iteration limit to prevent infinite loops
  • Potential overflow/underflow issues with very large/small numbers

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

Q2

Implement integer square root using binary search for n up to 2^63, with O(log n) iterations and no intermediate overflow. Specifically, compare mid <= n // mid instead of computing mid * mid.

Algorithms & Data Structures
Author's notes

Cleaner than the Newton's method part for me.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem constraints and edge cases, then explain the binary search strategy on the answer space [0, n]. Emphasize the overflow-safe comparison mid <= n // mid and analyze the O(log n) time complexity.

Pro tip: Mention that using integer division avoids overflow and is also faster than floating-point sqrt, which can have precision issues for large n. Also, note that the loop invariant ensures the answer is always within the search range.

1. Clarify requirements and edge cases

Confirm that n is a non-negative integer up to 2^63-1, and discuss handling of n=0 and n=1. Also, consider if the function should return the floor of the square root.

2. Define search space and invariant

Set low=0, high=n, and maintain that the answer lies in [low, high]. Use a while loop with low <= high, and compute mid = low + (high - low) // 2 to avoid overflow.

3. Implement overflow-safe comparison

Instead of mid*mid <= n, check mid <= n // mid. If true, move low to mid+1 and store mid as a candidate; else, move high to mid-1.

4. Return the result and analyze complexity

After the loop, return the stored candidate (or high). Explain that the search space halves each iteration, giving O(log n) time and O(1) space.

Key Points to Mention

  • Binary search on the answer space [0, n]
  • Overflow avoidance using mid <= n // mid instead of mid * mid
  • Time complexity O(log n) and space complexity O(1)
  • Handling edge cases: n=0, n=1, and perfect squares
  • Using mid = low + (high - low) // 2 to prevent overflow in midpoint calculation
  • Correctness proof via loop invariant and termination condition

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

Q3

Prove that Newton's method for computing square roots converges quadratically near the root.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

I knew the rough idea: write the error at step k+1 in terms of error at step k squared, cite the second-order Taylor expansion.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining the iteration x_{n+1} = (x_n + a/x_n)/2 for computing sqrt(a). Then show that the error e_n = x_n - sqrt(a) satisfies e_{n+1} = e_n^2 / (2 x_n), and bound this to get |e_{n+1}| ≤ C |e_n|^2 near the root, proving quadratic convergence. Finally, discuss the implications for practical use, such as the number of correct digits doubling each iteration.

Pro tip: Mention that quadratic convergence requires a good initial guess and that the method is self-correcting, but avoid overselling it—acknowledge that it can overshoot if the initial guess is poor, and relate it to real-world use cases like fast inverse square root in graphics or optimization in ML.

1. Define the iteration and error

State Newton's method for f(x)=x^2 - a: x_{n+1} = x_n - f(x_n)/f'(x_n) = (x_n + a/x_n)/2. Define the error e_n = x_n - sqrt(a).

2. Derive the error recurrence

Substitute x_n = sqrt(a) + e_n into the iteration and simplify to get e_{n+1} = e_n^2 / (2 x_n).

3. Bound the error for quadratic convergence

Assume x_n is close to sqrt(a), so x_n ≥ sqrt(a)/2. Then |e_{n+1}| ≤ (1/sqrt(a)) |e_n|^2, which is the definition of quadratic convergence.

4. Discuss convergence conditions and implications

Note that convergence is guaranteed if the initial guess is sufficiently close, and that the number of correct digits roughly doubles each iteration. Mention practical considerations like stopping criteria.

Key Points to Mention

  • Newton's method iteration formula for square roots: x_{n+1} = (x_n + a/x_n)/2
  • Definition of quadratic convergence: |e_{n+1}| ≤ C |e_n|^2
  • Error recurrence relation: e_{n+1} = e_n^2 / (2 x_n)
  • Requirement of a good initial guess for guaranteed convergence
  • Comparison to other methods (e.g., bisection) which converge linearly
  • Practical implications: doubling of correct digits per iteration, use in fast inverse square root and optimization

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

Q4

For inputs in the range 1e-12 to 1e12 with a specific initial guess strategy, estimate how many Newton iterations are needed to reach the given tolerance and justify your answer.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

This one tripped me up.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the function and tolerance, as Newton's convergence depends on the function's properties. Then, use the quadratic convergence formula to estimate iterations, considering the initial guess strategy and the wide input range. Finally, justify with worst-case and best-case scenarios, noting that the number of iterations is typically small (e.g., 5-10) due to quadratic convergence.

Pro tip: Mention that Newton's method doubles the number of correct digits each iteration, so for a tolerance of 1e-12, starting from a guess with 1 correct digit, about 4-5 iterations suffice. Also, highlight the importance of a good initial guess to avoid divergence or slow convergence.

1. Clarify the problem

Ask for the specific function, tolerance, and initial guess strategy if not provided. Assume a typical function like f(x)=x^2 - a for square root, and tolerance 1e-12.

2. Analyze convergence

Explain that Newton's method has quadratic convergence near the root, meaning the error roughly squares each iteration. Use the formula: if e_k is the error at step k, then e_{k+1} ≈ C e_k^2.

3. Estimate iterations

Given an initial guess with error e_0, the number of iterations to reach tolerance ε is approximately log2(log(ε)/log(e_0)) or use the rule of thumb: each iteration doubles the number of correct digits.

4. Consider the range

For inputs from 1e-12 to 1e12, a good initial guess strategy (e.g., using exponent bits) can ensure the initial relative error is bounded, leading to a consistent iteration count across the range.

5. Justify and conclude

State that typically 5-7 iterations are needed for double precision (1e-12 tolerance) regardless of the input magnitude, provided the initial guess is reasonable. Mention that without a good guess, iterations could be higher or diverge.

Key Points to Mention

  • Quadratic convergence of Newton's method
  • Error squaring each iteration
  • Number of correct digits doubles per iteration
  • Importance of initial guess for convergence and iteration count
  • Worst-case vs. average-case iteration estimates
  • Tolerance and machine precision limits

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

Q5

Compare the per-iteration cost and total operation count of Newton's method versus binary search for computing square roots of 64-bit integers.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Newton needs a division per step but converges in maybe 6-8 iterations for 64-bit numbers.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem: computing integer square roots for 64-bit integers, where exactness and efficiency matter. Compare Newton's method (quadratic convergence, ~6 iterations for 64-bit) and binary search (linear convergence, ~32 iterations) in terms of per-iteration cost and total operations. Conclude with practical trade-offs, noting that Newton's method is generally faster but may require careful handling of integer arithmetic and overflow.

Pro tip: Mention that Newton's method can be implemented with integer arithmetic and that the initial guess can be optimized (e.g., using bit length) to reduce iterations further. Also, note that binary search is simpler and less error-prone, which might be preferable in production code where robustness is critical.

1. Clarify the problem and constraints

Confirm that we are computing integer square roots for 64-bit unsigned integers, and that we care about both per-iteration cost and total operation count. Discuss whether exact integer results are required or if floating-point approximations are acceptable.

2. Analyze Newton's method

Explain that Newton's method for square root uses the iteration x_{k+1} = (x_k + n/x_k)/2. For 64-bit integers, it converges in about 6 iterations (quadratic convergence). Per iteration, it involves one division, one addition, and one shift (division by 2), which are relatively expensive operations.

3. Analyze binary search

Binary search for square root operates on the range [0, 2^32] (since sqrt(2^64) = 2^32). It takes about 32 iterations (log2(2^32) = 32). Each iteration involves a midpoint calculation, a multiplication (to square the midpoint), and a comparison, which are cheaper than division but more iterations are needed.

4. Compare per-iteration cost and total operations

Newton's method has higher per-iteration cost due to division (which is slow on modern CPUs), but far fewer iterations (6 vs 32). Binary search has lower per-iteration cost (multiplication and comparison) but more iterations. Estimate total operations: Newton ~6 divisions + ~12 additions/shifts; binary search ~32 multiplications + ~32 comparisons + ~32 additions.

5. Conclude with trade-offs and practical considerations

Summarize that Newton's method is typically faster in practice for 64-bit integers due to fewer iterations, despite division cost. However, binary search is simpler, branch-predictable, and avoids division, which can be advantageous in certain hardware or when code simplicity is prioritized. Mention that Newton's method may need careful handling to avoid overflow and ensure integer convergence.

Key Points to Mention

  • Newton's method converges quadratically, requiring ~6 iterations for 64-bit integers, while binary search requires ~32 iterations (linear convergence).
  • Per-iteration cost: Newton's method uses division (expensive), while binary search uses multiplication and comparison (cheaper).
  • Total operation count: Newton's method has fewer iterations but each is costlier; binary search has more iterations but each is cheaper.
  • Integer arithmetic considerations: Newton's method can be adapted for integers, but care must be taken to avoid overflow and ensure termination.
  • Initial guess optimization: For Newton's method, using the bit length to set an initial guess can reduce iterations further.
  • Practical trade-offs: Binary search is simpler and more robust; Newton's method is faster but more complex to implement correctly.

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

Q6

How would you extend the Newton's method implementation to return complex results for negative inputs under IEEE-754, and why can naive if/else branching be unsafe in that context?

Technical Trade-offsSystem Design
Author's notes

Genuinely did not see this coming.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify that Newton's method for square roots can be extended to negative inputs by returning complex numbers, but IEEE-754 floating-point arithmetic introduces edge cases like signed zeros, NaNs, and infinities. Then, explain that naive if/else branching on the sign of the input can be unsafe because it may mishandle these special values or introduce branch mispredictions, and propose a branchless or carefully guarded approach using copysign or complex arithmetic.

Pro tip: Mention that in production systems like Uber's, numerical robustness and performance are critical, so you'd use branchless techniques or library functions (e.g., cmath.sqrt) that handle IEEE-754 edge cases correctly, and you'd validate with property-based testing.

1. Clarify the goal and constraints

State that the goal is to compute the square root of a negative number using Newton's method, returning a complex result, while adhering to IEEE-754 semantics. Emphasize that the input may be -0.0, -inf, or NaN.

2. Explain the mathematical extension

Describe how Newton's method for sqrt(x) can be adapted to complex numbers by initializing with a complex guess and iterating z = (z + x/z)/2. For negative real x, the result should be i*sqrt(|x|).

3. Identify IEEE-754 pitfalls

Discuss how signed zeros, infinities, and NaNs propagate. For example, -0.0 should return -0.0 (or +0.0?) per IEEE-754, and -inf should return i*inf, but naive branching might treat -0.0 as negative and return i*0.0, which is incorrect.

4. Explain why naive if/else is unsafe

Naive if (x < 0) fails for -0.0 (since -0.0 < 0 is false) and for NaN (comparisons are false). Also, branching can cause performance issues due to misprediction and may not handle all edge cases uniformly.

5. Propose a robust solution

Suggest using copysign or signbit to detect the sign bit, or better, use a branchless approach: compute sqrt(|x|) and then multiply by i if the sign bit is set. Alternatively, use complex arithmetic from the start, ensuring the initial guess handles negative inputs.

Key Points to Mention

  • IEEE-754 special values: -0.0, -inf, NaN, and their behavior in comparisons.
  • Signed zero: -0.0 is equal to 0.0 but has a distinct sign bit; naive x < 0 fails to detect it.
  • Branch prediction and performance: if/else can cause pipeline stalls; branchless code is often faster and more predictable.
  • Complex Newton iteration: z_{n+1} = (z_n + x/z_n)/2 with complex arithmetic.
  • Use of copysign, signbit, or fabs to handle sign without branching.
  • Testing edge cases: property-based testing with NaN, infinities, and signed zeros.

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