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);
}
}