69. Sqrt(x)
On LeetCode ->Problem¶
Given a non-negative integer x, return the integer part of \(\sqrt{x}\).
-
Do not use exponentiation or built-in square root helpers.
-
Example:
Key trick¶
Use binary search on the answer, not on the value itself.
- Search the largest
midwithmid * mid <= x. - This gives \(O(\log x)\) time.
Trap¶
The common mistakes are:
- Returning the first
midthat satisfiesmid * mid <= x, instead of the largest one. - Using floating-point math, which can be imprecise.
- Forgetting edge cases like
x = 0andx = 1. - Writing a brute-force loop, which is too slow for large
x.
Why is it interesting?¶
It tests whether you can turn a math problem into a monotonic search problem.
- The predicate
mid * mid <= xis monotonic. - That makes binary search a natural interview solution.
Python solution¶
class Solution:
def mySqrt(self, x: int) -> int:
# We want the largest r such that r*r <= x.
l, r = 0, x
while l <= r:
mid = (l + r) // 2
square = mid * mid
if square <= x:
l = mid + 1
else:
r = mid - 1
return r
Commented your solution¶
Your first solution is correct and idiomatic.
- It uses binary search and has \(O(\log x)\) time.
return left - 1is equivalent to returningrightat the end.- The brute-force version is correct but too slow for interview constraints.
## Solution
# Works - in O(log(x))
class Solution:
def mySqrt(self, x: int) -> int:
left, right = 0, x
while left <= right:
mid = (left + right) // 2
if mid*mid <= x:
left = mid + 1
else:
right = mid - 1
return left - 1
Solution().mySqrt(8)
# Works - but brute force so slow
class Solution:
def mySqrt(self, x: int) -> int:
# we're looking for integer y such y*y <= x and (y+1)*(y+1) > x
# - we can do it brut force
# - or binary search
y = 0
while y*y <= x:
y += 1
return y - 1
Solution().mySqrt(8)