leetcode 精选top面试题 - 69. x 的平方根

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)。
 
posted @ 2020-12-05 21:19  Lucky小黄人^_^  阅读(132)  评论(0编辑  收藏  举报