69.力扣LeetCode_x的平方根
目录
方法一:牛顿迭代法
方法二:二分法
两种方法总结与差异
牛顿迭代法
二分法
性能差异
结论

-
方法一:牛顿迭代法
牛顿迭代法公式推导
第一步 选点
第二步 计算切线
第三步 计算切线在x轴的截距
第四步 将截距作为新的选点的横坐标
通过“判断两次迭代结果的差值是否小于预设精度阈值”来控制精度:核心逻辑是,用牛顿迭代公式 a2=0.5*(a1 + x/a1) 算出新近似值a2 后,调用 fabs(a1 - a2) 计算上一轮近似值 a1与新值a2的绝对值差值,再将这个差值和精度标准 1e-7(即 0.0000001)做比较——若差值小于1e-7,说明两次迭代的结果已经接近到“小数点后7位”的程度,继续迭代的精度提升微乎其微,此时就停止循环,确保最终返回的 a2(转换为整数前)满足预设的精度要求;若差值不满足,则将a2赋值给a1进入下一轮迭代,直到精度达标。
int mySqrt(int x) {if(x==0) return 0;double a1=x,a2;while(1){a2=0.5*(x/a1+a1);if(fabs(a1-a2)<1e-7) break;a1=a2;}return (int)a2;
}
-
方法二:二分法
思路
需要找到 ≤根号x 的最大整数。选取0作为左边界left,x本身作为右边界right,当left≤right时,取左右边界的平均值作为中间值mid。如果mid^2≤x,那说明此时的mid有可能是答案,将ans的值更新,并将left更新为mid+1。如果mid^2>x,此时的mid不可能是最终的答案,ans不更新,将right更新为mid-1
两处防溢出代码细节
mid=left+(right-left)/2
if((long)mid*mid<=x)
int mySqrt(int x) {if(x==0) return 0;int left=0,right=x,mid,ans=-1;while(left<=right){mid=left+(right-left)/2;if((long)mid*mid<=x){ans=mid;left=mid+1;}else{right=mid-1;}}return ans;
}
-
两种方法总结与差异
-
牛顿迭代法
牛顿迭代法通过不断逼近平方根的值来求解,核心思想是通过几何切线的方式逐步缩小误差。具体步骤是:首先选择一个初始猜测值 a1,然后根据迭代公式 a2 = 0.5 * (a1 + x/a1) 计算出新的猜测值 a2,并与上一次的值 a1 比较。如果两次迭代结果的差值小于预设的精度阈值(例如 1e-7),就可以停止迭代。否则,将 a2 作为新的初始值继续迭代。通过这种方式,牛顿迭代法能迅速逼近平方根,通常只需要 3-5 次迭代就能达到很高的精度。最终,通过将浮点数结果转为整数,得出 ≤√x 的最大整数。
优点:
快速收敛:每次迭代都能够大幅度缩小误差,通常只需要较少的迭代次数。
精度控制:通过设置精度阈值,可以控制计算的精度
缺点
浮点数运算:涉及浮点数的除法和加法运算,这些操作相对耗时且容易受到计算机精度限制(浮点数误差)影响。
不直接适配整数:虽然计算结果是整数,但实际上计算过程中需要处理浮点数,因此相对复杂,不如二分法直接。
-
二分法
二分法通过在整数范围内不断缩小搜索区间来求解 ≤√x 的最大整数。具体而言,首先设定搜索区间的左右边界为 0 和 x,然后计算区间中点 mid,判断 mid^2 是否小于等于 x。如果是,则 mid 可能是答案,将 mid 记录为答案,并将搜索区间的左边界更新为 mid + 1。否则,右边界更新为 mid - 1,继续缩小搜索区间。直到左右边界相交,得到最终结果。
优点:
完全基于整数运算:避免了浮点数计算的复杂性和潜在误差,所有计算都在整数范围内进行,确保精度。
适配性强:完全符合题目要求,直接求解整数平方根,尤其适合整数问题。
缺点:
迭代次数较多:二分法的迭代次数通常比牛顿迭代法要多,特别是在处理较大的 x 时(例如 x = 2147483647 时,需要大约 30 次迭代),但每次迭代的计算非常简单且高效。
-
性能差异
1. 计算复杂度
牛顿迭代法:每次迭代的时间复杂度为 O(1),但是每次迭代都需要进行浮点数除法和加法操作,这些操作的计算复杂度较高,因此尽管迭代次数较少,但每次迭代的时间成本较大。总体上,牛顿迭代法的迭代次数为 O(log x)(通常 3-5 次),但每次迭代的计算复杂度较高。
二分法:每次迭代的时间复杂度同样是 O(1),但是由于每次迭代仅进行整数的加减和乘法操作,这些操作非常快速。虽然二分法的迭代次数较多,通常是 O(log x),但每次迭代的计算开销较小。
2. 硬件适配性
牛顿迭代法:浮点数运算需要依赖 CPU 的浮点运算单元(FPU),浮点数的运算比整数运算更复杂,导致每次迭代的时间较长,尤其是在大数据量下。
二分法:完全基于整数运算,整数运算的速度比浮点运算快得多,尤其是在现代计算机中,整数加法、乘法和比较的操作速度更快,性能更加优越。
3. 稳定性与精度
牛顿迭代法:虽然迭代次数较少,但由于浮点数运算的复杂性和精度限制,可能会遇到浮点数误差,特别是在极大的 x 或者对极高精度的需求时,需要特别注意误差累积。
二分法:由于完全基于整数运算,二分法非常稳定,精度始终得到保证,特别适合处理整数范围内的精确计算。
-
结论
牛顿迭代法虽然迭代次数少,但由于浮点数运算的复杂性,计算速度较慢,尤其在硬件层面可能受到性能限制。它适合需要高精度浮点数计算的场景。
二分法虽然需要更多的迭代次数,但由于每次迭代仅涉及简单的整数运算,性能非常高,尤其适合求解整数平方根这类问题,因此在该问题中通常表现更优,既高效又稳定。
总体来说,对于求解“最大整数平方根”这类问题,二分法更适合,因为它能够提供更快的执行速度、更高的稳定性,并且完全满足题目对整数输出的需求。
