LeetCode:x的平方根

1、题目描述

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

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

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

示例 1:

输入:x = 4
输出:2

示例 2:

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

提示:

  • 0 <= x <= 231 - 1

2、暴力破解

思路
  • **0**开始遍历,依次计算,直到找到第一个i使得i² > x
  • 返回**i-1**,因为(i-1)² ≤ x < i²,即i-1x的平方根的整数部分。
时间复杂度
  • O(√x),最坏情况下需要遍历到i ≈ √x
适用场景
  • 优点:简单直接,适合小范围x
  • 缺点:当x很大时(如x=10^9),效率低。
//暴力破解
    static int bf(int x){
        for (int i = 0; i < x; i++) {
            if (i * i > x){
                return i-1;
            }
        }
        return -1;
    }

3、二分法查找

思路
  • 初始化搜索范围l = 0r = x
  • 二分查找
    • 计算中间值mid
    • 如果mid² ≤ x,说明平方根可能更大,更新index = mid并向右搜索(l = mid + 1)。
    • 如果mid² > x,说明平方根更小,向左搜索(r = mid - 1)。
  • 返回**index**,即最大的满足mid² ≤ xmid
时间复杂度
  • O(log x),每次将搜索范围减半。
适用场景
  • 优点:高效,适合大范围x(如x=10^18)。
  • 缺点:需要理解二分查找的边界条件。
//二分法,但是该方法如果x足够大的话,会超出Int类型的最大值,会mid * mid出现数值溢出,从而导致计算错误!
    static int binarySearch(int x){
        int index =-1;
        int l=0,r=x;
        while (l<=r){
            int mid = l + (r-l)/2;
            if (mid * mid <= x){
                index = mid;
                l = mid + 1;
            }else {
                r = mid - 1;
            }
        }
        return index;
    }

当测试用例**x = 2147395599****,二分查找会出现错误。这是因为:**

  1. 数值溢出mid * mid可能超过int的最大值(2^31 - 1 = 2147483647),导致计算错误。
  2. 边界条件x的平方根是46340(因为46340^2 = 2147395600,刚好大于2147395599),但某些实现可能返回46339或错误结果。

修复后的二分查找

以下是修复后的二分查找实现,解决数值溢出问题:

修正思路
  1. 避免直接计算**mid * mid**:

    改用mid <= x / mid判断,防止mid * mid溢出。

  2. 调整搜索范围

    初始化右边界r = x,但可以优化为r = x / 2 + 1(因为sqrt(x) ≤ x/2 + 1)。

//二分法改进:
    static int newBinarySearch(int x) {
        if (x == 0 || x == 1) return x; // 处理边界
        int l = 1, r = x / 2 + 1;      // 优化右边界
        int ans = 0;
        while (l <= r) {
            int mid = l + (r - l) / 2;
            if (mid <= x / mid) {      // 避免 mid * mid 溢出
                ans = mid;
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        return ans;
    }

4、牛顿迭代

求x的平方根,可以转化为 x = n ^2,求n,=⇒ n = x / n

由数学推理可知,当 ( n + x/n) 的平均数要比n或者x/n 都要接近x的平方根,也就是(n + x/n ) /2 无限接近于 x的平方根。因此我们可以使用递归来无限次求 (n + x/n )/2 来无限接近,直到doubl的边界的时候,两者就是相等的时候。

思路
  • 牛顿迭代公式

    通过迭代逼近平方根,公式为:

    n = (n + x / n) /2

    其中x是待求平方根的数,n是当前近似值。

  • 终止条件:当两次迭代结果几乎相同时(res == i),认为已收敛。

  • 返回整数部分:最终结果强制转换为int

时间复杂度
  • O(log x),收敛速度极快,通常只需几次迭代。
适用场景
  • 优点:数学上高效,适合需要高精度或大数计算。
  • 缺点:涉及浮点数运算,可能因精度问题导致无限循环(需设置最大迭代次数)。
//牛顿迭代
    static int newton(int x){
        if (x == 0) return 0;
        return (int)sqrt(x,x);
    }
    static double sqrt(double i, int x){
        double res = (i + x/i) / 2;
        if (res == i){
            return i;
        }else {
            return sqrt(res, x);
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值