java数据结构与算法刷题-----LeetCode69:x 的平方根

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.youkuaiyun.com/grd_java/article/details/123063846

在这里插入图片描述

1. 数学

解题思路:时间复杂度O( 1 1 1),空间复杂度O( 1 1 1)

通过自然对数换底,将其换为其它两个数学操作: x = x 1 2 = e l n x 1 2 = e 1 2 l n x \sqrt{x} = x^\frac{1}{2} = e^{lnx^\frac{1}{2}} = e^{\frac{1}{2}lnx} x =x21=elnx21=e21lnx

代码

在这里插入图片描述

class Solution {
    public int mySqrt(int x) {
        if (x == 0) return 0;
        //Math.exp(a)表示对a做自然对数,求lna
        int ans = (int) Math.exp(0.5 * Math.log(x));
        //计算机无法存储浮点数精确值,指数函数和对数函数都返回浮点数,运算过程会有偏差
        //当求Integer.MAX_VALUE等较大值,例如x = 2147395600,Math.exp(0.5 * Math.log(x));的计算结果与正确值46340差10^-11
        //此时我们取值时,会得到46339这个错误的结果,也就是取值后相差1
        //所以如果求出的数+1相乘后 <= 原来的数,就返回ans+1.否则说明没有偏差到取整差1,返回ans本身
        return (long) (ans + 1) * (ans + 1) <= x ? ans + 1 : ans;
    }
}

2. 二分查找法

解题思路:时间复杂度O( l o g 2 x log_2x log2x),空间复杂度O( 1 1 1)
  1. x的平方根的整数部分ans就是 k 2 k^2 k2 <= x的最大k值.我们对k进行二分查找,从而提高查找效率
  2. 我们知道x的一半x/2的平方是 >= x的, 因此k的范围就是[0,x/2],我们对这个范围进行二分查找
代码

在这里插入图片描述

class Solution {
    public int mySqrt(int x) {
        if(x==1) return 1;
        int l = 0, r = x/2;//二分查找的范围
        int ans = -1;//保存结果
        while (l <= r) {//如果还有的查就继续
            int mid = l + (r - l) / 2;//获取l和r的mid
            if ((long) mid * mid <= x) {//如果当前mid比x的平方根小
                ans = mid;//保存mid
                l = mid + 1;//从mid右边区间继续
            } else {//如果mid比x平方根大
                r = mid - 1;//从mid左边区间继续找
            }
        }
        return ans;
    }
}

3. 牛顿迭代法

解题思路:时间复杂度O( l o g 2 x log_2x log2x),空间复杂度O( 1 1 1)
  1. 这是底层求平方根的库函数的常见实现方法。原理是高数中的微积分中的知识,但是属于超纲题
  2. 核心是通过迭代,也就是泰勒级数,不断逼近函数的零点。也就是找函数零点的一种方法
代码

在这里插入图片描述

class Solution {
    /**牛顿迭代法,可以算出小数,高数中的导数求零点的进阶知识
    * 例如 求根号2,我们先随便猜近似值4(猜多少都无所谓,越接近,越省时间),然后根据公式a = (a+x/a)/2
    *   迭代第一次 a = (4+2/4)/2 = 2.25
    *   第二次    a = (2.25+2/2.25)/2 = 1.56944....
    *   第三次    a = (1.56944...+2/1.56944...)/2 = 1.42189.....
    *   计算次数越多,越精确,但是如果你要用java算,不要超过精度
    *   比如我们可以精确到1e-7(10的-7次方精度0.0000001)
    *      如何判断精确到这个精度呢
    *          如果 |上一次的值-这次迭代的值|的绝对值 <1e-7 就说明精度到位了
    *   注意这个公式不能给0用
    * @param x
    * @return
    */
    public int mySqrt(int x) {
        if(x==0) return 0;//公式不能给0用
        //a是每次迭代结果,b是上一次迭代结果
        double a = x,b = x;
        while(true){
            //牛顿迭代公式,(当前迭代结果a+原值x/当前迭代结果a)/2
            a = (a+x/a)*0.5;//牛顿迭代,迭代次数越多精度越高
            //编程,确定精度方法,两次迭代结果的差的绝对值<指定精度,就说明精度到位了
            if(Math.abs(b-a)<1e-7) break;
            b = a;//否则b记录这次迭代结果
        }
        return (int)a;//题目要求,必须是整数
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ydenergy_殷志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值