x的平方根
给你一个非负整数 x
,计算并返回 x
的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意: 不允许使用任何内置指数函数和算符,例如 pow(x, 0.5)
或者 x ** 0.5
。
示例 1:
输入:x = 4
输出:2
示例 2:
输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
提示:
0 <= x <= 2^31 - 1
解题
解法一
思路分析:
- 根据题目提示,x的范围在
0 <= x <= 2^31-1
,如果是暴力循环遍历求解寻找平方根,会超时,所以我们考虑使用二分来搜索平方根。 - 使用二分时,我们需要考虑
if
判断条件,同时我们可以根据算术平方根的性质有x = a*a, a >= 2, a*a/2 > a
即二分搜索的终点可以缩减为x/2
实现代码如下:
class Solution {
public int mySqrt(int x) {
if (x == 0 || x == 1) // 若x为1或2则算术平方根为x本身直接返回即可
return x;
// 当 x >= 2时 由算数平方根的性质可以得出 x的算术平方根a 一定 < x/2
int end = x / 2;
// 使用二分来搜索
int start = 1;
while (start < end) {
int mid = ((end - start) >> 1) + start;
if ((long)mid * mid > x) {
end = mid;
} else {
start = mid + 1;
}
}
// 返回结果刚好是x的算术平方根的两边整数端点
// 根据题意返回左端点
if (start*start > x) start -= 1;
return start;
}
}
提交结果如下:
解答成功:
执行耗时:1 ms,击败了94.10% 的Java用户
内存消耗:39.1 MB,击败了5.01% 的Java用户
复杂度分析:
- 时间复杂度:O(log x)
- 空间复杂度:O(1)
总结:
在if
判断中,mid*mid
会导致溢出,因此需要将类型改为long
,同时返回值有可能是在x算术平方根的两边端点,需要返回更小的端点