算法20,x的平方根

笔记记录了经典的**"二分查找求平方根"** 问题。这是二分查找算法在非有序数组场景下的一个重要变种 ,核心是利用数学函数的单调性来应用二分法。

以下是对该笔记内容的详细解析和标准代码实现:

1. 算法原理

对于一个非负整数 x,其平方根函数 f(k)=k2在 k≥0的区间内是单调递增的。

  • 单调性:如果 k1​<k2​,那么 k12​<k22​。

  • 二段性 :我们可以在区间 1,x上查找,对于任意中间值 mid:

    • 如果 mid * mid <= x:说明平方根在 [mid, x]之间(或者 mid就是答案,需尝试更大的值看是否有更接近的)。

    • 如果 mid * mid > x:说明平方根一定在 [1, mid - 1]之间。

2. 笔记关键点解析

  • 边界条件 :if(x < 1) return 0;。这是为了处理 x=0的情况,防止后续 right=x导致死循环或越界。

  • 搜索区间 :left = 1, right = x。对于 x≥1,其平方根不会超过 x本身。

  • 防溢出技巧:

    • 笔记中使用了 long mid = ...。

    • 原因 :在计算 mid * mid时,如果 x接近整型最大值(约 21 亿),mid约为 10 万,mid * mid将达到 100 亿,远超 int的范围(约 21 亿),导致整数溢出 ,计算结果变为负数从而出错。使用 long类型可以完美规避这个问题。

3. 代码实现(Java)

复制代码
public class SqrtX {
    public int mySqrt(int x) {
        // 特殊情况处理:0的平方根是0
        if (x < 1) return 0;
        
        // 定义搜索区间 [left, right]
        int left = 1;
        int right = x;
        
        while (left <= right) {
            // 计算 mid,使用 long 防止乘法溢出,使用 left + (right - left) / 2 防止加法溢出
            long mid = left + (right - left) / 2;
            
            long square = mid * mid;
            
            if (square == x) {
                // 正好找到完全平方数
                return (int) mid;
            } else if (square < x) {
                // 平方小于 x,说明平方根在右边,尝试更大的数
                left = (int) mid + 1;
            } else {
                // 平方大于 x,说明平方根在左边
                right = (int) mid - 1;
            }
        }
        
        // 循环结束时,left > right。
        // 此时 right 指向的是平方小于等于 x 的最大整数(即向下取整的结果)。
        // 举例:x=8, 循环结束时 right=2, left=3。返回 right。
        return right;
    }
}

4. 进阶:牛顿迭代法(拓展)

虽然二分查找是该题的标准解法,但计算机科学中求解平方根更高效的算法是牛顿迭代法(Newton's Method)。它的收敛速度比二分查找更快(二次收敛)。

核心思想:通过不断作切线来逼近方程 f(k)=k2−x=0的根。

迭代公式:kn+1​=21​(kn​+kn​x​)

复制代码
public int mySqrtNewton(int x) {
    if (x == 0) return 0;
    double C = x;
    double x0 = x;
    while (true) {
        // 牛顿迭代公式
        double xi = 0.5 * (x0 + C / x0);
        // 如果变化量极小,认为已经收敛到精确解
        if (Math.abs(xi - x0) < 1e-7) break;
        x0 = xi;
    }
    return (int) x0;
}
相关推荐
星夜离尘564 小时前
MATLAB 工程实验:不等间隔流量积分,先把缺口与覆盖率说清楚
开发语言·matlab·时间戳·数据质量·数值积分
happylifetree4 小时前
Python70:核心语法-函数进阶-案例2
python
Ai-_Man4 小时前
Meta Muse还是不可以导出左侧所有对话,只能点进去单条内容导出,方法不对吗?
开发语言·人工智能·ai·小程序·c#·1024程序员节
梓豪csd4 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
王中阳Go4 小时前
两个入口答案不一致先别调模型:6 行入口口径对账表(附脚本)
人工智能·后端·python·大语言模型·1024程序员节
BK贝壳4 小时前
bool-hybrid-array 落盘我只认 .bha:用 Create_BHA / Ask_BHA 做布尔数组序列化
数据结构·python·numpy·1024程序员节
学逆向的5 小时前
C 枚举变量
c语言·开发语言·网络安全
Sakura_j_h_5 小时前
Python 在定时任务里输出 emoji,UnicodeEncodeError 从哪来
开发语言·字符编码·windows·python·定时任务
supabc1236 小时前
欧盟电子发票(XRechnung/Peppol/ZUGFeRD)踩坑记:用 Python 不装 Java 跑官方校验规则
xml·python·开源·电子发票·1024程序员节
ZhengEnCi6 小时前
AI Agent工具调用防护层怎么写-一份能直接跑的Python四层拦截实现
python·llm·agent