给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
示例 1:
输入:x = 4
输出:2
示例 2:
输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842…, 由于返回类型是整数,小数部分将被舍去。
提示:
0 <= x <= 231 - 1
题解1 袖珍计算器算法
class Solution {
public:
int mySqrt(int x) {
if (x == 0) {
return 0;
}
int ans = exp(0.5 * log(x));
return ((long long)(ans + 1) * (ans + 1) <= x ? ans + 1 : ans);
}
};
直白一点
class Solution {
public:
int mySqrt(int x) {
if(!x) return x;
long long i = 1;
while(i < x/2){
if(x >= i*i && x < (i+1)*(i+1))
return i;
i ++;
}
return i;
}
};
题解2 二分查找
class Solution {
public:
int mySqrt(int x) {
int l = 0, r = x, ans = -1;
while (l <= r) {
int mid = l + (r - l) / 2;
if ((long long)mid * mid <= x) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
}
};
题解3 牛顿迭代
class Solution {
public:
int mySqrt(int x) {
if (x == 0) {
return 0;
}
// y = x^2 - C , 设xi是y上的点 (xi, xi^2-C)
// 做切线: y' = 2xi(x-xi)+xi^2-C
// y' = 0 时, xi+1 = 1/2(xi+C/xi)
// 每一次迭代后,我们都会距离零点更进一步,所以当相邻两次迭代得到的交点非常接近时(1e-6或1e-7)就可视为答案
double C = x, x0 = x;
while (true) {
double xi = 0.5 * (x0 + C / x0);
if (fabs(x0 - xi) < 1e-7) {
break;
}
x0 = xi;
}
return int(x0);
}
};