69. x 的平方根
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4 输出: 2
示例 2:
输入: 8 输出: 2 说明: 8 的平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
法一:二分法
二分法,在1到x中寻找平方大于等于x的值,每次让mid * mid和x做比较,
如果mid*mid < x, 说明平方根在右区间,所以 right = mid - 1;
如果mid*mid > x, 说明平方根在左区间,所以 right = mid - 1;
如果mid*mid == x, 说明找到了平方根在左区间直接返回。
1 class Solution { 2 public int mySqrt(int x) { 3 // 二分法,在1-x中寻找平方小于等于x的最大值 4 int left = 1, right = x; 5 long temp = (long)x; 6 while(left <= right){ 7 int mid = (right + left) / 2; 8 long sqare = mid * mid; 9 if(sqare == temp){ 10 return mid; 11 }else if(sqare < temp){ 12 left = mid + 1; 13 }else{ 14 right = mid - 1; 15 } 16 } 17 return left - 1; 18 } 19 }
上面的方法其实当x特别大的时候,会有整数溢出的问题。mid * mid会超出long类型所能表示的最大整数范围,所以必须采用 x / mid 与 mid做比较来取代 mid * mid 与x作比较,这样就不会有溢出的问题。
参考:https://leetcode-cn.com/problems/sqrtx/comments/88428
1 class Solution { 2 public int mySqrt(int x) { 3 // 二分法,在1-x中寻找平方小于等于x的最大值 4 if(x == 0 || x == 1){ 5 return x; 6 } 7 int left = 0, right = x; 8 while(left <= right){ 9 int mid = (right - left) / 2 + left; 10 int sqrt = x / mid; // x / mid与mid比较,避免溢出 11 if(sqrt == mid){ 12 return mid; 13 }else if(sqrt > mid){ 14 left = mid + 1; 15 }else{ 16 right = mid - 1; 17 } 18 } 19 return left - 1; 20 } 21 }
leetcode :执行用时:1 ms, 在所有 Java 提交中击败了100.00%的用户, 内存消耗:35.6 MB, 在所有 Java 提交中击败了67.92%的用户
复杂度分析:
时间复杂度:O(logn)。使用二分法求出了平方根,所以时间复杂度为O(logn)。
空间复杂度:O(1)。只借助了一些常量的变量空间,所以空间复杂度为O(1)。