0% completed
Solution: Sqrt
On This Page
Problem Statement
Solution
Step-by-Step Algorithm
Algorithm Walkthrough
Code
Complexity Analysis
Time Complexity
Space Complexity
Problem Statement
Given a non-negative integer x, return the square root of x rounded down to the nearest integer. The returned integer should be non-negative as well.
You must not use any built-in exponent function or operator. For example, do not use pow(x, 0.5) in C++ or x ** 0.5 in Python.
Example 1:
Input: x = 8
Output: 2
Explanation: The square root of 8 is 2.8284, and since we need to return the floor of the square root (integer), hence we returned 2.
Example 2:
Input: x = 4
Output: 2
Explanation: The square root of 4 is 2.
Example 3:
Input: x = 2
Output: 1
Explanation: The square root of 2 is 1.414, and since we need to return the floor of the square root (integer), hence we returned 1.
Constraints:
- 0 <= x <= 2<sup>31</sup> - 1
Solution
We can use a Binary Search approach to calculate the square root of an integer x without using any in-built sqrt function.
For any integer x of 4 or more, the square root of x is never greater than x / 2. So the answer always lies between 0 and x / 2, and binary search only has to look inside that range. We are searching for the largest integer y whose square is less than or equal to x, which is the floor of the square root.
The smaller values are handled without a search. For x of 0 or 1 the function returns x at once. For x of 2 or 3, left starts at 2 and right is x / 2, which is 1 in integer division. The loop condition left <= right is already false, so the loop never runs and the function returns right, which is 1. That is the correct answer for both.
This approach ensures an efficient and accurate computation of the square root, especially for large values of x, due to the logarithmic nature of binary search.
Step-by-Step Algorithm
- Handle Base Cases: If
xis less than 2, returnxdirectly (since the square root of 0 is 0, and the square root of 1 is 1). - Initialize Pointers: Set
leftto 2 andrighttox / 2. - Binary Search Loop:
- While
leftis less than or equal toright:- Calculate
midasleft + (right - left) // 2. - Calculate
numasmid * mid. - If
numis greater thanx, moverighttomid - 1. - If
numis less thanx, movelefttomid + 1. - If
numequalsx, returnmid.
- Calculate
- While
- Return Result: Return
rightas the integer part of the square root ofx.
Algorithm Walkthrough
Let's consider the input n = 8:
-
Initialize:
- Input
x = 8. - Since
xis not less than 2, proceed to the next step. - Set
left = 2andright = 4(8 // 2).
- Input
-
First Iteration:
- Calculate
mid = 2 + (4 - 2) // 2 = 3. - Calculate
num = 3 * 3 = 9. - Since
num(9) is greater thanx(8), moverighttomid - 1 = 2.
- Calculate
-
Second Iteration:
- Now
left = 2andright = 2. - Calculate
mid = 2 + (2 - 2) // 2 = 2. - Calculate
num = 2 * 2 = 4. - Since
num(4) is less thanx(8), movelefttomid + 1 = 3.
- Now
-
End Loop:
- Now
left = 3andright = 2. - Since
left(3) is greater thanright(2), exit the loop.
- Now
-
Return Result:
- Return
right = 2as the integer part of the square root ofx = 8.
- Return
Code
Here is the code for this algorithm:
Complexity Analysis
Time Complexity
-
Binary Search Algorithm: The key part of this algorithm is the binary search, which repeatedly divides the search interval in half. The time complexity of binary search is O(log n), where n is the size of the search space. In this case, the search space is initially from
2tox/2. -
Search Space: The maximum size of the search space is
x/2(when x \geq 4). For smaller values ofx, the function immediately returnsx, as it's either0or1. -
Overall Time Complexity: Considering the binary search on a range up to
x/2, the time complexity is O(log(x/2)), which simplifies to O(\log x).
Space Complexity
-
Constant Extra Space: The algorithm uses a fixed number of integer variables (
left,right,pivot,num), regardless of the input size. -
No Recursive Calls or Dynamic Allocation: The implementation does not use recursion or allocate additional data structures that grow with the input size.
-
Overall Space Complexity: Given the constant amount of extra space, the space complexity is O(1), meaning it's constant.
Anonymous
· 3 years ago
I just wanted to suggest a more subtle way of explaining it that may be a bit better. So, binary search is applied here because we are searching for a value in a specific range of values, which is a range of sorted numbers. That value we are looking for is the largest value n such that n * n <= x. So, we can use a variable to store the result, and if we ever find a value whose square is <= x, update the result to that. However, since our goal is to find the largest, toss that pivot out and set left = mid + 1. If the square is too large, then we want to lower our right bound and set right = mid - 1.
class Solution { public int mySqrt(int x) { int left = 0; int right = x; int res = 0; while(left <= right){ int mid = left + (right - left) / 2; if((long
Roberto Pantoja
· 3 years ago
I came up with the following solution.
class Solution { public: int mySqrt(int x) { int i = 0; while(i * i <= x){i++;} // TODO: Write your code here return i - 1; } };
Basically, just increment i until you pass the square root, then return previous value.
Am I missing something? Why is the more complex solution the example?
Vishnu S Nair
· a year ago
For any integer x, the square root of x will lie between 0 and x/2 (inclusive) for x > 2.
The upper bound rule does not always hold for small values of x, particularly for x = 3.
Jlsegb
· 7 months ago
You can ask an LLM to explain it. But this is a neat way of calculating a root. Probably better to use the binary tree solution but this one performs better O(log log n)
class Solution { public: int mySqrt(int x) { if (x == 0) return 0; int r = x; while (r > x / r) { // instead of r*r > x r = (r + x / r) / 2; // this is Newton's method. } return (int)r; // floor(sqrt(x)) } };
Note that we should avoid a possible integer overflow from r*r by re-arranging the equality or using a bigger container.
Manuel
· 2 years ago
As you first stated sqrt (x) is in the range 0 - x/2
Then, why are you doing this verification if (num > x) instead of if (num > x/2) ?
Thanks
vladyslav.chikov
· 9 months ago
There is a solution which in terms of big-O notation is not that good as binary search, but good enough for the most of modern numbers.
The first instinct you want to go is:
class Solution: def mySqrt(self, x: int) -> int: i = 0 step = 1 while (i+1) * (i+1) <= x: i += 1 return i
This algo is O(X^{1/2}) which is not bad and will work on any modern CPU all the way till 10^14-10^16
But you quickly realise that if your input is, say, 10**16, and you do i = 1, then likely do i=2,3,4,5 is pretty useless.
Instead we can do an incremental jump size too to increase the growth. Once we cross the bar, we slow down the growth until it stops:
class Solution: def mySqrt(self, x: int) -> int: i = 0 step = 1 while (i+step) * (i+step) <=
On This Page
Problem Statement
Solution
Step-by-Step Algorithm
Algorithm Walkthrough
Code
Complexity Analysis
Time Complexity
Space Complexity