Implement a fast integer square root function that takes in an integer and returns another integer that is the floor of the square root of the input.
用二分搜索的思想,找到一个区间[low, low+1],使得low*low<=target<=(low)*(low+1)。
int searchSqrtFloor(int target) { return searchUtil(target, 1, target); } int searchUtil(int target, int l, int r) { if(l+1 == r) return l; else if(l+1<r) { int m = l+ (r-l)/2; if(m*m == target) return m; else if(m*m < target) return searchUtil(target, m, r); else if(m*m > target) return searchUtil(target, l, m); } }
注意:上面的算法对于3个corner case: target=0 、target=1 和 target = 2,都是不适用的。还要注意,直接求 m*m < target 容易产生溢出,求 m < target/m 更安全。下面给出一个对所有大于等于零的自然数成立的算法, 注意区间的开和闭。
int sqrt(int x) { if(x<0) return -1; if(x==0) return 0; int l=1; int r=x/2+1; while(l<=r) { int m = (l+r)/2; if(m<=x/m && x/(m+1)<m+1) return m; if(x/m<m) { r = m-1; } else { l = m+1; } } return 0; }
上面的算法稍加改动,就能变成“找出最近的平方数”,代码如下:
int searchNearestSquare(int target) { return searchUtil(target, 1, target); } int searchUtil(int target, int l, int r) { if(l+1 == r) target-l*l > r*r-target ? return r : return l; else if(l+1<r) { int m = l+ (r-l)/2; if(m*m == target) return m; else if(m*m < target) return searchUtil(target, m, r); else if(m*m > target) return searchUtil(target, l, m); } }