早岁已知世事艰,仍许飞鸿荡人间
—— 24.3.24
x 的平方根
给你一个非负整数
x
,计算并返回x
的 算术平方根 。由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如
pow(x, 0.5)
或者x ** 0.5
。注:是小数部分都被舍去,不是四舍五入
二分查找法 思路分析
从题目的要求和示例我们可以看出,这其实是一个查找整数的问题,并且这个整数是有范围的。
如果这个整数的平方恰好等于输入整数,那么我们就找到了这个整数;
如果这个整数的平方严格大于输入整数,那么这个整数肯定不是我们要找的那个数;
如果这个整数的平方严格小于输入整数,那么这个整数可能是我们要找的那个数(重点理解这句话)。
因此我们可以使用「二分查找」来查找这个整数,不断缩小范围去猜。猜的数平方以后大了就往小了猜;
猜的数平方以后恰恰好等于输入的数就找到了;
猜的数平方以后小了,可能猜的数就是,也可能不是。
很容易知道,题目要我们返回的整数是有范围的,直觉上一个整数的平方根肯定不会超过它自己的一半,但是 000 和 111 除外,因此我们可以在 111 到输入整数除以 222 这个范围里查找我们要找的平方根整数。000 单独判断一下就好。
public class Solution {
public int mySqrt(int x) {
// 特殊值判断
if (x == 0) {
return 0;
}
if (x == 1) {
return 1;
}
// 区间左临界
int left = 1;
// 区间右临界
int right = x / 2;
// 在区间 [left..right] 查找目标元素
while (left < right) {
int mid = left + (right - left + 1) / 2;
// 注意:这里为了避免乘法溢出,改用除法
if (mid > x / mid) {
// 下一轮搜索区间是 [left..mid - 1]
right = mid - 1;
} else {
// 下一轮搜索区间是 [mid..right]
left = mid;
}
}
return left;
}
}