69.求平方根
- 给你一个非负整数 x,计算并返回x的算术平方根
- 由于返回类型是整数,结果只保留 整数部分,小数部分将被舍去
- 不允许使用任何内置指数函数和算符,如
pow(x,0.5)
方法一:暴力破解
从 i = 0 i=0 i=0 开始遍历,直到满足 i 2 ≤ x < ( i + 1 ) 2 i^2 \leq x < {(i+1)}^2 i2≤x<(i+1)2 时, i i i 即是 x x x 的算术平方根。
代码实现
int mySqrt(int x) {
int nRes = 0;
int a = nRes * nRes;
int b = 0;
while (a <= x) {
//防止(nPow + 1) * (nPow + 1)移除,(nPow + 1) * (nPow + 1) = nPow * nPow + 2 * nPow + 1
if (a < INT_MAX - 2 * nRes - 1) {
b = (nRes + 1) * (nRes + 1);
}
else {
break;
}
if (a <= x && b > x) {
break;
}
nRes++;
}
return nRes;
}
时间复杂度: O ( x ) O(x) O(x)
空间复杂度: O ( 1 ) O(1) O(1)
方法二:数学计算
利用公式:
x = x 1 / 2 = ( e ln x ) 1 / 2 = e 1 2 ln x \sqrt{x} = x^{1/2} = {(e^{\ln{x}})}^{1/2} = e^{\frac{1}{2}\ln{x}} x=x1/2=(elnx)1/2=e21lnx
由于计算机无法存储浮点数的精确值,而指数函数和对数函数的参数和返回值均为浮点数,因此运算过程中会存在误差。因此在得到结果的整数部分 a n s ans ans 后,还要验证 a n s ans ans 和 a n s + 1 ans+1 ans+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);
}
};
时间复杂度: O ( 1 ) O(1) O(1)
空间复杂度: O ( 1 ) O(1) O(1)
方法三:二分查找
在方法一的基础上进行优化,方法一的遍历范围 [0,x] ,利用二分查找在该范围进行查找可以降低计算复杂度。
代码实现
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;
}
};
时间复杂度: O ( log x ) O(\log{x}) O(logx)
空间复杂度: O ( 1 ) O(1) O(1)