Understand
30-second explanation
Build the interview-ready mental model before comparing implementations.
Return the floor of √x without using a built-in sqrt. Binary-search the answer space [0, x]: for each candidate mid, ask 'is mid ≤ √x?' by testing mid ≤ x/mid (NOT mid*mid ≤ x, which overflows). Converge to the largest integer whose square is ≤ x in O(log x) time.
Interview contextWhat is testedWhere candidates slipHow to stand outExplore interview contextHide interview context
What's being tested
Whether you recognize that the answer space is monotonic and binary-searchable, and whether you write the comparison in an overflow-safe way (mid ≤ x/mid) instead of the tempting mid*mid ≤ x.
Where candidates slip
Writing `mid * mid <= x`, which overflows 32-bit int for large x (e.g. x near 2³¹), or computing `mid = (lo + hi) / 2` and overflowing the sum.
How to stand out
Frame it as binary search on the answer, justify monotonicity, use `mid <= x / mid` to dodge overflow, and mention Newton's method as the O(log x) alternative with faster constant factors.
Choose
Compare the available approaches
Use constraints and trade-offs to select the route you can defend in an interview.
Interactive decision treeInteractiveChoose the right approachFirst decision previewInteger floor of √xBuilt-in sqrt allowed?YesNoExplore the full treeCollapse the tree
Learn & trace
Build each solution step by step
Move from the core idea to a visual trace, implementation, proof, and edge cases.
Approach 1 of 2
Linear Scan
1Hint 1Explore hintHide hint
The answer is the largest k with k² ≤ x. What's the simplest way to find it — just try k = 0, 1, 2, … in order?
2Hint 2Explore hintHide hint
Increment k until k² first exceeds x. The previous k is your answer (the floor).
3Hint 3Explore hintHide hint
This works but does ~√x iterations — up to ~46340 for max x. Fine for small x, but we can do far better with binary search.
A · Core idea
The most literal reading: the floor of √x is the largest integer k with k² ≤ x, so just count up from 1 and stop the moment k² exceeds x. The last k that still satisfied the bound is the answer.
Why this is correct. The function k → k² is strictly increasing on non-negative integers, so there's a single crossover point where k² first passes x. Everything before it satisfies k² ≤ x; everything after fails. Walking upward and stopping at the first failure lands us exactly one past the answer, so we return k − 1 (or track the last good k).
Why it's already overflow-aware. Even here, k * k can overflow as k approaches ~46340 and we test one step too far. So we phrase the loop condition as k <= x / k rather than k * k <= x — the same division trick the optimal solution leans on. This keeps every intermediate value inside 32-bit range.
Why we don't ship it. O(√x) ≈ 46,000 iterations for the largest input is fast in absolute terms but needlessly linear. Because the predicate k² ≤ x is monotonic, we can binary-search the crossover in O(log x) ≈ 31 steps instead. Mention this approach to anchor correctness, then optimize.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
x = 8k=1
1 ≤ 8/1=8 → ok
ans = 12C · Code with teaching comments
Reference implementation previewpublic int mySqrt(int x) { if (x < 2) { return x; } int k = 1;Explore the full codeHide the full code
D · Why it works and complexityO(√x) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
Even the naive scan should use k <= x / k, not k * k <= x — the overflow trap exists regardless of approach. Establishing the monotonic predicate k² ≤ x here is what justifies binary search next.
ComplexityO(√x) time, O(1) space — We test k = 1, 2, …, √x until the square exceeds x — about √x iterations, each O(1). For x ≈ 2³¹ that's ~46k steps.
E · Edge cases and pitfalls5x = 0 — x < 2 guard returns 0 directly, avoiding division by zero.Explore edge casesHide edge cases
Edge cases handled
x = 0x < 2 guard returns 0 directly, avoiding division by zero.x = 1x < 2 guard returns 1.
Pitfalls
- Writing `k * k <= x` — overflows as k nears 46340.
- Dividing by k when k could be 0 — guard x < 2 first.
- Returning k instead of k - 1 — off by one at the crossover.
Approach 2 of 2 · Optimal
Binary Search on the Answer (Optimal)
1Hint 1Explore hintHide hint
The predicate 'mid² ≤ x' is true for small mid and false for large mid — a single monotonic flip. What technique finds that boundary in log time?
2Hint 2Explore hintHide hint
Binary-search mid in [0, x]. If mid² ≤ x, mid is a feasible answer — record it and search higher (lo = mid + 1). Otherwise search lower (hi = mid - 1).
3Hint 3Explore hintHide hint
Critical: test `mid <= x / mid`, NOT `mid * mid <= x`, to avoid 32-bit overflow. Also compute mid as `lo + (hi - lo) / 2` to avoid overflowing the sum.
A · Core idea
Because k → k² is monotonic, the candidates split cleanly into a feasible prefix (mid² ≤ x) and an infeasible suffix (mid² > x). The floor of √x is the last feasible value — the boundary between the two regions — and finding a monotonic boundary is exactly what binary search does in O(log x).
Searching the answer, not the input. There's no array here. The 'array' we binary-search is the conceptual range of possible answers [0, x]. We pick the middle candidate mid, ask the yes/no question "is mid ≤ √x?", and discard half the range based on the answer. When mid² ≤ x, mid is a valid (possibly-not-maximal) answer, so we record it and push lo = mid + 1 to hunt for something larger. When mid² > x, mid is too big, so hi = mid - 1. The loop ends having recorded the largest feasible mid — the floor.
Why `mid <= x / mid` and not `mid * mid <= x`. This is the crux of the problem. For x near 2³¹, a candidate mid near 46340 has mid * mid ≈ 2.1 billion, right at the 32-bit ceiling — and one step beyond, 46341² ≈ 2.147e9 overflows INT_MAX, wrapping to a negative number and silently corrupting the comparison. Rewriting it as mid <= x / mid is algebraically the same test (divide both sides of mid² ≤ x by mid) but every value stays comfortably within range. The alternative is to widen to a 64-bit long for the product, but the division form needs no wider type at all. Guarding x < 2 up front keeps mid from being 0 in that division.
The other overflow you must dodge. Computing mid = (lo + hi) / 2 can overflow when lo + hi exceeds INT_MAX. Writing mid = lo + (hi - lo) / 2 computes the same midpoint without ever forming the dangerous sum. Two overflow traps, two idioms — interviewers notice when you handle both.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
x = 8Interactive diagram
Monotonic predicate the search exploits
lo=0, hi=8mid² ≤ x is true then false exactly once. Binary search finds that boundary.
2C · Code with teaching comments
D · Why it works and complexityO(log x) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
Two ideas make this click: (1) binary-search the answer range whenever a monotonic predicate splits it into yes/no halves, and (2) rewrite mid * mid <= x as mid <= x / mid to sidestep overflow without a wider type. That predicate-on-the-answer framing is reusable across Koko Eating Bananas, Split Array Largest Sum, and Capacity to Ship Packages.
ComplexityO(log x) time, O(1) space — Each step halves the search range [0, x], so ~log₂(x) ≈ 31 iterations for max x, each O(1). Only a few scalar variables → O(1) space.
E · Edge cases and pitfalls7x = 2147395600 — mid reaches 46340; 46340 ≤ x/46340 holds, 46341 fails. mid*mid would overflow here — division stays safe. Returns 46340.Explore edge casesHide edge cases
Edge cases handled
x = 2147395600mid reaches 46340; 46340 ≤ x/46340 holds, 46341 fails. mid*mid would overflow here — division stays safe. Returns 46340.x = 0x < 2 guard returns 0, sidestepping division by zero.x = 2mid=1 feasible (1 ≤ 2), mid=2 infeasible (2 ≤ 1 false). Returns 1.
Pitfalls
- `mid * mid <= x` — overflows for x near 2³¹; use `mid <= x / mid`.
- `mid = (lo + hi) / 2` — the sum can overflow; use `lo + (hi - lo) / 2`.
- Starting lo at 0 without the x < 2 guard — divides by zero at mid = 0.
- Returning lo or hi at the end instead of the recorded ans — off-by-one floor errors.
Practice
Try the solution yourself
Edit the optimal implementation, test another input, and observe the result.
Editable code previewpublic int mySqrt(int x) { if (x < 2) { return x; } int lo = 1, hi = x, ans = 0;Explore the playgroundClose the playground
Avoid mistakes
Recognize the interview traps
Understand why common attempts fail before reviewing the corrected implementation.
1Squaring mid overflows
For x near 2³¹, mid near 46341 makes mid*mid exceed INT_MAX and wrap negative, corrupting the comparison. Compare with division instead.
Explore the code comparisonHide the code comparison
Squaring mid overflows
For x near 2³¹, mid near 46341 makes mid*mid exceed INT_MAX and wrap negative, corrupting the comparison. Compare with division instead.
Don't write this
if (mid * mid <= x) {
ans = mid;
lo = mid + 1;
}Write this instead
if (mid <= x / mid) {
ans = mid;
lo = mid + 1;
}2Midpoint sum overflow
lo + hi can exceed INT_MAX when hi is large (up to x = 2³¹−1). Compute the midpoint without forming the sum.
Explore the code comparisonHide the code comparison
Midpoint sum overflow
lo + hi can exceed INT_MAX when hi is large (up to x = 2³¹−1). Compute the midpoint without forming the sum.
Don't write this
int mid = (lo + hi) / 2;Write this instead
int mid = lo + (hi - lo) / 2;3Division by zero on mid = 0
If lo starts at 0 and x is 0, mid can be 0 and `x / mid` divides by zero. Guard the x < 2 case and start lo at 1.
Explore the code comparisonHide the code comparison
Division by zero on mid = 0
If lo starts at 0 and x is 0, mid can be 0 and `x / mid` divides by zero. Guard the x < 2 case and start lo at 1.
Don't write this
lo, hi = 0, x
mid = (lo + hi) // 2
if mid <= x // mid: # ZeroDivisionError when mid == 0
...Write this instead
if x < 2:
return x
lo, hi = 1, xRevise
Carry the pattern into the interview
Pattern to remember
Binary search on the answer
Code pattern to memorize
lo, hi = 0, x
while lo <= hi:
mid = lo + (hi - lo) // 2
if mid <= x // mid: # equivalent to mid*mid <= x, overflow-safe
ans, lo = mid, mid + 1
else:
hi = mid - 1
return ansRules to remember
- 1Compare `mid <= x / mid`, never `mid * mid <= x` — squaring a large mid overflows a 32-bit int. Division stays in range.
- 2Search the ANSWER, not the input — the candidate sqrt lives in
[0, x], andmid² ≤ xis monotonic, so binary search applies. - 3Use `mid = lo + (hi - lo) / 2` to avoid
lo + hioverflowing for large bounds. - 4Track the last valid mid (
ans = midwhenmid² ≤ x) — the loop overshoots, so the recorded answer is the floor. - 5Handle x = 0 and x = 1 — both return themselves; make sure
midis never 0 in thex / middivision (start lo at 1 or guard x < 2).
Use this pattern when
- Find the integer floor/ceil of a monotonic function (sqrt, cube root, nth root)
- Answer lies in a numeric range and a predicate on it is monotonic
- Built-in math functions are disallowed and you need integer precision
- 'Largest value satisfying a condition' / 'smallest value that breaks it'
Choose another pattern when
- A library sqrt is allowed and floating-point precision is acceptable → just call it and floor
- You need full floating-point precision, not the integer floor → Newton's method or library
- x is tiny and bounded → a simple linear scan is clear enough
- The function isn't monotonic → binary search on the answer doesn't apply
Interview takeaway
Sqrt(x) is the entry point to 'binary search on the answer': when you can phrase the problem as 'find the largest k with predicate(k) true' and the predicate is monotonic, binary-search the value range. The overflow-safe `mid <= x/mid` comparison is the detail interviewers look for, and the same template solves Valid Perfect Square, Koko Eating Bananas, and Split Array Largest Sum.
Continue
Transfer the pattern to another problem
Use a direct variation or pattern sibling to prove the idea is reusable.
Transferable patternBinary search on the answer space, guarded against overflow. Recognise it whenever you must find the largest/smallest integer satisfying a monotonic predicate without a closed form: integer sqrt, perfect square, Koko Eating Bananas, Split Array Largest Sum. The `mid <= x / mid` rewrite is the reusable overflow-avoidance trick.
Practice queueDirect variations and pattern siblings
Direct follow-ups
- Valid Perfect SquareComing soonSame binary search, but return whether mid² exactly equals x rather than the floor.
- Pow(x, n)The inverse operation — compute xⁿ in O(log n) via fast exponentiation.
- Koko Eating BananasComing soonBinary search on the answer (eating speed) under a monotonic feasibility predicate.
- Find the Smallest Divisor Given a ThresholdComing soonSame 'binary search the answer' template with a monotonic sum-of-ceilings predicate.