题目
实现 int sqrt(int x)
函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
思路
个人认为这题要做好,算是中等难度的题目了;
最简单的思路一定是从 i=0
开始试探,每次令 i += 1
,再判断 i*i
与 x 的大小关系,这样遍历一定是可以找到答案的;
提交可以通过,但是耗时17ms,显然不是最优解,其实这是可以优化的,我们从 0 → i 0 \rightarrow i 0→i 遍历,是一个有序地序列,竟然有序,就可以采用二分的思路;
这个题有一个需要注意的地方,我们在判断 mid
与 _x_大小关系时,需要考虑 mid*mid
超出 int
范围的问题,根据题目要求,所有数据应该在 int
范围内,所以我们的二分区间可以直接写死 0~46340
,因为所有答案都在这个区间内;
还有一个需要注意的地方是:
mid*mid > x
,右区间修改为mid-1
;mid*mid < x
,左区间修改为mid
;
这是特别需要注意的地方,情况1 mid-1
是很好理解的,因为 mid
偏大,当然需要减小,情况2为什么不能 +1
呢?因为开放可能得到小数,如2开放得到1.414,当 mid=1
偏小时,+1
又会导致偏大,从而跳出了答案区间;
代码
public class Solution {
public int mySqrt(int x) {
int left = 0, right = 46340, mid, e;
while (left != right) {
mid = (int) ((left+right)/2.0 + 0.5);
e = mid*mid;
if (e > x)
right = mid-1;
else if (e == x)
left = right = mid;
else
left = mid;
}
return left;
}
public static void main(String[] args) {
Solution solution = new Solution();
int a = 2147395599;
System.out.println(solution.mySqrt(a));
}
}