题目:
Implement int sqrt(int x)
.
Compute and return the square root of x.
思路:
这道题目挺有意思,虽然基本思路都是迭代查找,但是不同的思维可能会给出不同的解决方案:
1、二分查找法:码农很容易想到二分查找法(注意为了防止溢出,需要将左右边界的类型定义为long或者long long)。
2、牛顿迭代法:数学好的人都知道求实数的平方根可以采用牛顿迭代法,其思路也可以用在这里,写出来的代码简洁、优雅、漂亮。可是在int类型上的测试效率似乎不如二分查找法。
3、位操作法:硬件工程师估计会用位操作法来在硬件上实现求平方根。思路是从高到低逐位(bit)确定结果的值:首先确定最高位的值,然后依次尝试低一位的bit是否可以设置为1,只到处理完成所有位(bit)。
有一个笑话,说是如果问push的反义词是什么,一般人可能会说是pull;码农会说是pop(中毒已经有点深了O(∩_∩)O);而PhD们很可能会说是nice(估计已经快要被老板虐的体无完肤了~~~)。
言归正传:如果面试官问到这道题目,首先需要和他clarify清楚如果x < 0怎么办?另外在编写程序的时候一定要注意溢出的情况(采用long类型是一个不错的解决方法)。这两点很大程度上可以反映面试者思维的缜密程度以及编程的功力。
代码:
1、二分查找法:
class Solution {
public:
int mySqrt(int x)
{
if(x <= 0) // it is better to ask interviewer how to tackle x < 0
return 0;
long left = 1, right = x;
while(left <= right)
{
long mid = (left + right) / 2;
if(mid * mid > x)
right = mid - 1;
else
left = mid + 1;
}
return left - 1;
}
};
2、牛顿迭代法:
class Solution {
public:
int mySqrt(int x)
{
long g = x; // Newton's mehod
while(g*g > x)
g = (g + x/g) / 2;
return g;
}
};
3、位操作法:
class Solution {
public:
int mySqrt(int x)
{
if(x == 0 || x == 1) // Bit manipulation
return x;
int h = 0;
while((long)(1 << h) * (long)(1 << h) <= x)
h++;
h--;
int res = (1 << h); // the maximum power of 2
int d = h - 1;
while(d >= 0)
{
if((long)(res | 1 << d)*(long)(res | 1 << d) <= x)
res |= (1 << d);
d--;
}
return res;
}
};