难度:简单java
题库地址:leetcode-cn.com/problems/sq…算法
实现 int sqrt(int x)
函数。数组
计算并返回 x 的平方根,其中 x 是非负整数。bash
因为返回类型是整数,结果只保留整数的部分,小数部分将被舍去。函数
示例 1:spa
输入: 4
输出: 2
复制代码
示例 2:code
输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 因为返回类型是整数,小数部分将被舍去。
复制代码
计算x
的平方根,这里暂不考虑各类求平方根的计算公式。cdn
最简单的方法就是i
从0开始以步长1递增,当遇到第一个数i
,使得i * i > x
,那么i - 1
就是要找的数。固然这里有个问题,i * i
可能致使计算结果溢出变成死循环。正确的退出条件是当i > x / i
,这样变化后须要注意i
不能为0。对象
Java实现:blog
public int mySqrt(int x) {
if (x < 2) {
return 0;
}
int i = 1;
while (i <= x / i) {
i++;
}
return i - 1;
}
复制代码
以上算法能够理解为在[1, x]
中找数i
,由于这里的[1, x]
已经按升序排好顺序,因此可使用二分查找法减小查找次数。 这里比较麻烦的地方是如何调整查找区间和找到循环终止条件。和在排好序的数组中查找一个数的位置不一样的是:这里要查找数x的平方根整数部分。刚开始把问题想的很复杂,好比:
实时证实这些考虑只是在给本身挖坑,在Mr__Kim的评论里说明了一种简单明了的解决办法,对于这个算法有以下优势:
x = 0
的状况Java代码以下:
public int mySqrt(int x) {
int l = 1;
int r = x;
// 默认结果为0,若是x = 0,不会进入循环,直接退出
int ans = 0;
while (l <= r) {
int mid = l + (r - l) / 2;
// 要找的结果是真正平方根的向下取整值,
// 因此 mid <= x / mid 时,随着查找分区的调整,这个 mid 就无限逼近于最后要找的值
// 最后当退出循环时,这个 ans 就保存了最接近于真正的平方根的值,如 4 -> 2,8 -> 2
if (mid <= x / mid) {
// 实时保存最接近于平方根的结果
ans = mid;
// 因为当 mid == x / mid 时,已经将当前 mid 值保留了下来,因此下一次调整分区没必要包含 mid
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
}
复制代码
运行结果: