Leetcode刷题69. x 的平方根

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:

输入:x = 4
输出:2
示例 2:

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
 

提示:

0 <= x <= 231 - 1

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/sqrtx
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

感谢大神liweiwei1419的二分查找(Java),感谢LOAFER的牛顿迭代法。

class Solution {
    public int mySqrt(int x) {
//		return mySqrtI(x);
		return mySqrtII(x);
//		return mySqrtIII(x);
	}

	//方法三:牛顿迭代法
	//时间复杂度O(logx),空间复杂度O(1)
	//首先随便猜一个近似值x,然后不断令x 等于 x和 a/x的平均数,迭代个六七次后 x的值就已经相当接近根号a的近似值
	private int mySqrtIII(int x) {
		long r = x;
		while (r * r > x) {
			r = (r + x / r) / 2;
		}
		return (int) r;
	}

	//方法二:二分搜索,从两边向中间以二分的方式进行夹击
	//时间复杂度O(logx),空间复杂度O(1)
	private int mySqrtII(int x) {
		if (x == 0 || x == 1) {
			return x;
		}
		int left = 2;
		int right = x / 2 + 1;
		int mid = -1;
		while (left <= right) {
			mid = left + (right - left) / 2;
			if (mid <= x / mid && (mid + 1) < x / (mid + 1)) {
				return mid;
			}
			if (mid < x / mid) {
				left = mid + 1;
			} else {
				right = mid - 1;
			}
		}
		return mid;
	}

	//方法一:二分查找右侧边界
	//时间复杂度O(logx),空间复杂度O(1)
	//如果一个数的平方根恰好等于输入整数,则就是该数。
	//如果一个数的平方根大于输入整数,则不可能是该数。
	//如果一个数的平方根小于输入整数,则有可能是该数。
	//查找一个数,且这个数是有范围的,可以使用二分查找来查找这个整数,不断缩小范围去猜。
	private int mySqrtI(int x) {
		if (x <= 1) {
			return x;
		}
		//除了0和1,一个数的整数平方根肯定不会超过它自己的一半
		int left = 2, right = x / 2 + 1;
		while (left < right) {
			int mid = left + (right - left) / 2;
			if (mid <= x / mid) {
				left = mid + 1;
			} else {
				right = mid;
			}
		}
		//这里其实就是二分搜索右侧边界(可以理解为需要获取最接近的那个数,所以使用右侧边界)
		return right - 1;
	}
}

问题延伸:如何求浮点数的平方根?

Java 二分法 求浮点数的平方根 保留小数

你可能感兴趣的:(数组,数学,二分查找)