要求:Implement
int sqrt(int x)
. Compute and return the square root of x.
解决方法:
1.牛顿法(Newton's method)
化解:计算 x2 = a 的解,令 y = x2 - a,相当于求解 y = 0 的解,f(x) 如图。
第一步:取 x0 = a / 2 , 如果 x0 不是解,在点( x0,y0) 做切线 y - y0 = (x - x0) * y'0 ,与 x 轴的交点为 x1 = x0 - y0 / y'0 = x0 - (x02 - a) / (2x0) = (x0 + a / x0) / 2 。
第二步:如果 x1 不是解,做一个经过 ( x1,y1) 这个点的切线,与x轴的交点为 x2。
…………
结束条件:
a. f( xi ) ≈ 0;
b. xi ≈ xi-1.
代码:
inline double ABS(double x){
return x > 0 ? x : (-1 * x);
} class Solution {
public:
int sqrt(int x) {
/* 用牛顿迭代法求浮点数的平方根 */
double g0 = 0, g1 = x;
while(ABS(g1-g0) > 0.9)
{
g0 = g1;
g1 = (g0 + (x / g0)) / 2;
}
return floor(g1); // (int)g1
}
};
2. 分治法(Divide and conquer)
a = 0 时,返回 0.
a = 1 时,返回 1.
a > 1 时,返回的数在序列 1 与 a/2 之间,序列有序,所以可以用二分法查找。
代码如下:
class Solution {
public:
int sqrt(int x){
/*********** 二分法 ************/
/*********************************/
if(x == 0) return 0;
if(x == 1) return 1;
unsigned long long begin = 1, end = x >> 1;
while(begin < end)
{
unsigned long long mid = (begin + end) >> 1;
unsigned long long tem = mid * mid;
if(tem == x) return mid;
else if(tem > x) end = mid -1;
else begin = mid + 1;
}
if(begin = end)
{
unsigned long long tem = end * end;
if(tem <= x) return end;
if(tem > x) return end - 1;
}
else return end;
}
};
3. 构造数字
从高位到低位,依次试探添加 1。
class Solution {
public:
int sqrt(int x) {
int ans = 0;
int bit = 0X40000000;
while(bit > 0) {
ans |= bit;
if (ans > x / ans) {
ans ^= bit;
}
bit >>= 1;
}
return ans; }
};