【每日一题】x 的平方根

69. x 的平方根

关键词:袖珍计算器算法、二分查找、牛顿迭代

题目来源:69. x 的平方根 - 力扣(Leetcode)

题目描述

 T袖珍计算器算法
 T二分查找
 T牛顿迭代

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

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

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

输入:x = 4
输出:2
输入:x = 8
输出:2
数据范围 
0 <= x <= 2^31 - 1

袖珍计算器算法

「袖珍计算器算法」是一种用指数函数和对数函数代替平方根函数的方法。

根据√x=e1/2lnx,从而得到√x的值。由于浮点数的值是不精确的,所以结果可能存在差一错误,需要添加额外判断。

int mySqrt(int x) {
    if (!x)return x;
    int res = exp(0.5 * log(x));
    return (long long) (res + 1) * (res + 1) <= x ? res + 1 : res;
}

时间复杂度:O(1)

空间复杂度:O(1)

二分查找

x的平方根的整数部分res必定是满足k2≤x的最大k。若有k1不满足k2≤x,则小于k1的k也不满足k2≤x,故k具有单调性,因此可采用二分来求解。k的下界为0,上界不妨定为x。

int mySqrt(int x) {
    if (x < 2)return x;
    int l = 1, r = x, mid;
    while (l < r) {
        // r-l+1可能会溢出
        mid = l + ((r - l + 1) >> 1);
        if (mid > x / mid)r = mid - 1;
        else l = mid;
    }
    return l;
}

时间复杂度:O(log(n))

空间复杂度:O(1)

牛顿迭代

牛顿迭代法可以用来快速求解函数零点。

令C表示待求出平方根的那个整数,显然C的平方根就是函数y=f(x)=x2-C的零点。

任取一点xi作为初始值,找到函数上的点(xi, f(xi)),过该点做函数的切线,交x轴于xi+1,xi+1相较于xi距离零点更近,多次迭代后,就能得到一个距离零点非常近的交点。

点(xi, f(xi))处函数的切线的斜率为2xi,故直线切线方程为yi=2xix-(xi2+C),得与x轴的交点xi+1=(xi+C/xi)/2。

由于y=f(x)=x2-C有两个零点,为了得到正的那个零点,xi的初始值应该取C。最后的结果会稍稍大于正零点。

int mySqrt(int x) {
    if (x < 2)return x;
    double C = x, x1 = 0, x2 = x;
    while (fabs(x2 - x1) > 1e-7) {
        x1 = x2;
        x2 = (x2 + C / x2) / 2;
    }
    return int(x2);
}

时间复杂度:O(log(n))。此方法是二次收敛的,相较于二分查找更快。

空间复杂度:O(1)

posted @ 2023-05-05 11:18  字节幺零二四  阅读(37)  评论(0)    收藏  举报
努力加载评论中...
编辑推荐:
· 一个 java 空指针异常的解决过程
· 揭开 SQL Server 和 PostgreSQL 填充因子的神秘面纱
· 没有调度器的协程不是好协程,零基础深入浅出 C++20 协程
· 别做抢活的导演:代码中的抽象层次原则
· 从 Redis 客户端超时到 .NET 线程池挑战
阅读排行:
· 会Vibe Coding的同事:我一个人干掉整个技术部!
· 回答准确率从60%飙至95%!AI知识库救命方案
· dotnetty 内存泄漏的BUG修复了
· 20250709 - GMX V1 攻击事件: 重入漏洞导致的总体仓位价值操纵
· 线上问题定位神器:Arthas
点击右上角即可分享
微信分享提示