Integer square root without a library
Given a non-negative integer x, return ⌊√x⌋, the largest integer whose square
is at most x. Do not use a square-root function or exponentiation from a library.
Examples
| Input | Output | Why |
|---|---|---|
x = 8 | 2 | 2² = 4 ≤ 8 < 9 = 3². |
x = 16 | 4 | |
x = 2147483647 | 46340 | 46340² = 2,147,395,600; 46341² overflows a 32-bit integer. |
Constraints
- 0 ≤ x ≤ 2³¹ − 1
Hints
Hint 1
The test "r² ≤ x" is true for r = 0, 1, 2, … up to some point, then false for ever. You want the last true.
Hint 2
Search r in [0, x]. When the test passes, mid could be the answer, so keep it: lo = mid. Which way must mid round to avoid an infinite loop?
Hint 3
mid² for mid near 2³¹ does not fit in 32 bits. Use 64-bit arithmetic, or compare mid with x / mid.
Where people lose marks
- Rounding mid down while setting lo = mid: with lo = 3, hi = 4 the loop spins on mid = 3 for ever.
- Computing mid * mid in 32 bits.
- Starting hi at x / 2 and forgetting x = 1, whose root is 1.
Dry run on 50
Read it one frame at a time, the way you would trace the code on paper in an interview. Each frame shows the state after the step it describes.
-
Step 1 / 8lo0hi50
Candidates 0 to 50. "r² ≤ 50" holds up to some point and then fails; we want the last r where it holds. mid rounds up.
-
Step 2 / 8lo0mid25hi50
25² = 625 > 50. 25 fails, so does everything above it: hi = 24.
-
Step 3 / 8lo0mid12hi24
12² = 144 > 50. 12 fails, so does everything above it: hi = 11.
-
Step 4 / 8lo0mid6hi11
6² = 36 ≤ 50. 6 works, so the answer is 6 or larger: lo = 6.
-
Step 5 / 8lo6mid9hi11
9² = 81 > 50. 9 fails, so does everything above it: hi = 8.
-
Step 6 / 8lo6mid7hi8
7² = 49 ≤ 50. 7 works, so the answer is 7 or larger: lo = 7.
-
Step 7 / 8lo7mid8hi8
8² = 64 > 50. 8 fails, so does everything above it: hi = 7.
-
Step 8 / 8answer7
lo = hi = 7: 7² = 49 ≤ 50 < 64 = 8². The answer is 7.
How to think about it
There is no array here, only a test on whole numbers: r² ≤ x. It holds for
r = 0 and keeps holding until r passes √x, then fails for every larger
r. The answer is the last r for which it holds, so this is binary search over the
candidates 0 … x.
Searching for the last true needs one change from searching for the first true. When mid passes
it stays in the range, lo = mid; when it fails, hi = mid − 1. With two candidates left,
lo + (hi − lo) / 2 rounds down to lo, a pass sets lo = mid = lo, and the loop
never ends. Rounding the midpoint up, lo + (hi − lo + 1) / 2, fixes it.
mid can be as large as 2³¹ − 1, and mid² then needs 62 bits. Compute it in 64 bits, or
test mid ≤ x / mid with integer division, which is equivalent for positive mid and cannot
overflow.
Thirty-one steps cover every 32-bit input. Newton's method, r ← (r + x / r) / 2, converges faster
and is a good follow-up answer, but its stopping rule is easier to get wrong under pressure.
Complexity. Time O(log x) · Space O(1)
The solution, in six languages
Each one is compiled and run against the test table before it is published. Java is reviewed by hand.
def my_sqrt(x):
lo, hi = 0, x # the answer is in [lo, hi]
while lo < hi:
mid = (lo + hi + 1) // 2 # round up, or lo = mid never moves
if mid * mid <= x:
lo = mid # mid works; the answer is mid or larger
else:
hi = mid - 1
return lolong long solve(long long x) {
long long lo = 0, hi = x; // the answer is in [lo, hi]
while (lo < hi) {
long long mid = lo + (hi - lo + 1) / 2; // round up, or lo = mid never moves
if (mid * mid <= x) lo = mid; // 64-bit: mid < 2^31, so mid * mid < 2^62
else hi = mid - 1;
}
return lo;
}class Solution {
public int mySqrt(int x) {
long lo = 0, hi = x; // the answer is in [lo, hi]
while (lo < hi) {
long mid = lo + (hi - lo + 1) / 2; // round up, or lo = mid never moves
if (mid * mid <= x) lo = mid; // long: no overflow
else hi = mid - 1;
}
return (int) lo;
}
}function mySqrt(x) {
let lo = 0, hi = x; // the answer is in [lo, hi]
while (lo < hi) {
const mid = lo + Math.ceil((hi - lo) / 2); // round up
if (mid * mid <= x) lo = mid; // exact wherever it matters: near x the square is below 2^32
else hi = mid - 1;
}
return lo;
}fn solve(x: i64) -> i64 {
let (mut lo, mut hi) = (0i64, x); // the answer is in [lo, hi]
while lo < hi {
let mid = lo + (hi - lo + 1) / 2; // round up, or lo = mid never moves
if mid * mid <= x { lo = mid } else { hi = mid - 1 }
}
lo
}solve :: Int -> Int
solve x = go 0 x
where
-- the answer is in [lo, hi]; mid rounds up so that lo = mid always moves
go lo hi
| lo >= hi = lo
| mid * mid <= x = go mid hi
| otherwise = go lo (mid - 1)
where mid = lo + (hi - lo + 1) `div` 2
Variants to try
- Return the square root to six decimal places: binary search over reals for a fixed number of rounds, or over integers scaled by 10⁶.
- Decide whether x is a perfect square: compute r and test r² = x.
- The integer k-th root: the same search with an overflow-safe power check.
Next problems
Complete rows of a coin staircase
Row k needs k coins, so k complete rows need k(k + 1)/2. Search for the last k that fits, with 64-bit arithmetic.
Open the problem → Easy10 minFind a value in a sorted array
The search every other binary search is built on: halve a closed range until the value is found or the range is empty.
Open the problem → Easy10 minThe top of a mountain array
Nothing is sorted, but "is the next element smaller?" is false up the slope and true down it. Find the first true.
Open the problem →Write a solution and run it against the real test table.
Keep going
Complete rows of a coin staircase
Row k needs k coins, so k complete rows need k(k + 1)/2. Search for the last k that fits, with 64-bit arithmetic.
Open the problem → Easy10 minFind a value in a sorted array
The search every other binary search is built on: halve a closed range until the value is found or the range is empty.
Open the problem → Easy10 minThe top of a mountain array
Nothing is sorted, but "is the next element smaller?" is false up the slope and true down it. Find the first true.
Open the problem → Binary searchThe pattern behind it
Search the answer, not the array: halve a monotone predicate until one candidate is left.
Read the pattern →Preparing for a real process? Quant interview preparation, or book a free 20-minute call.