classSolution { public: intmySqrt(int x){ //i have a non-negative integer. //non-negative means i can be 0 or greater than 0. //i need to find the square root of x and if x is not an integer, then round it down. // if x=2, then mid=0+2/2=1 // mid^2<2, so check right part=[mid,x]=[1,2], left=mid=1, mid=1+2/2=1 // loop should meet: left+1<=right // int left=0, right=x; // if x=3,then mid=0+x/2=1 // 1^2<3, so check right part=[1,3], left=1, mid=2 // 2^2>3, so check left part=[1,2], right=2, mid=1 // 1^2<3, so check right part=[1,2] long left=0, right=x; for(;;){ long mid=left+((right-left)>>1); long mul=mid*mid; if(mul==x) { return mid; }elseif(mul<x) { //check right if(left+1==right){ if(right*right==x) { return right; } else { return left; } } left=mid; }else { //check left if(left+1==right) { if(right*right==x) { return right; }else { return left; } } right=mid; } } } };
If you don’t use long, you can use trick mid==x/mid. But be careful, 0 cannot be denominator.
classSolution { public: intmySqrt(int x){ if(x==0){ return0; } int left=1, right=x; for(;left<=right;){ int mid=left+(right-left)/2; if(mid==x/mid){ return mid; }elseif(mid>x/mid){ //check left right=mid-1; }else{ //check right left=mid+1; } } //if does not find, then left > right, return smaller one return right; } };
About return value:
Say we have only two elements: [1,2]. mid is 1, in the front. right=mid-1 cause exit and we want the round down. right < left, so return right.
Say we have only 1 elements: [1]. mid is 1, in the front. left=mid+1 cause exit and we want round down. right < left, so return right.
[2023-09-26 Tue 14:55]
Notice that the candidate answer is always in “less branch”, thus we store the mid in that branch.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defmySqrt(self, x: int) -> int: low = 1 high = x ans = 0
while low <= high: mid = (low + high) // 2 if mid * mid == x: return mid elif mid * mid < x: low = mid + 1 ans = mid else: high = mid - 1 return ans