力扣题69Sqrt()

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

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

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

示例 1:

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

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

1.自己的解法:利用i*i和x的关系比较,取各种情况。但是这种方法在数字很大的时候,显示超出时间限制,需要想办法优化。

class Solution {
    public int mySqrt(int x) {
        int result = 0;
        for(int i = 0;i <= x;i++){//
            if(i*i == x){//找到
                result = i;
                break;
            }else if(i*i < x){//小于的话就跳过这次循环
                continue;
            }else{//大于的话,就取最后一个小于该值的值
                result = i - 1;
                break;
            }
        }

        return result;
    }
}

   发现导致时间超出限制的原因是i*i的时候可能溢出,在比较时将其转换为long类型即可。并且将循环方法改为二分查找,减小时间复杂度。

class Solution {
    public int mySqrt(int x) {
        int result = 0;
        int left = 0;
        int right = x;

        //找到最后一个i*i不大于x的i值即可。
        while(left <= right){
            int middle = (left + right)/2;

            if((long)middle*middle <= x){//防止middle*middle溢出
                result = middle;
                left = middle + 1;
            }else{
                right = middle - 1;
            }
        }

        return result;
    }
}

   另一种解决防止溢出的方法,用除法来替代乘法,但是要当心middle为0的情况,当middle为0的情况单独拿出来讨论:

class Solution {
    public int mySqrt(int x) {
        int result = 0;
        int left = 0;
        int right = x;

        if(x <= 1){//0,1的middle可能为0,不能做除法
            return x;
        }

        //找到最后一个i*i不大于x的i值即可。
        while(left <= right){
            int middle = (left + right)/2;

            if(middle <= x/middle){//防止middle*middle溢出
                result = middle;
                left = middle + 1;
            }else{
                right = middle - 1;
            }
        }

        return result;
    }
}

2.官方答案提供了一种解法:牛顿迭代法

   下面是官方提供的思路。

力扣题69Sqrt()_第1张图片力扣题69Sqrt()_第2张图片

class Solution {
    public int mySqrt(int x) {
        if(x == 0){
            return 0;
        }

        double c = x;
        double x0 = x;//用来保存当前的零点

        while(x0 >= 0){
            double xi = 0.5 * (x0 + c/x0);//新的零点

            if(Math.abs(x0 - xi) < 1e-7){//判断新的零点和上一个零点之间的距离
                break;
            }

            x0 = xi;
        }

        return (int)x0;
    }
}

题源:力扣

你可能感兴趣的:(力扣,leetcode,java)