实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

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

示例 1:

输入: 4
输出: 2

示例 2:

输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 
     由于返回类型是整数,小数部分将被舍去。

解题思路

首先可以想到的最简单的处理思路就是遍历[1,x]的所有元素i,计算相应的平方值,如果大于x的话,我们返回i-1即可。

class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        for i in range(x+1):
            if i**2 > x:
                return i - 1
        return x

但是这显然太过随意,时间复杂度太高。这个问题在数学上已经有很明确的解法了,就是大名鼎鼎的牛顿法。

首先,选择一个接近函数f(x)f(x)零点的x0x_0,计算相应的f(x0)f(x_0)和切线斜率f(x0)f^{'}(x_0)(这里ff^{'}表示函数ff的导数)。然后我们计算穿过点(x0,f(x0))(x_0,f(x_0))并且斜率为f(x0)f^{'}(x_0)的直线和xx轴的交点xx坐标,也就是求如下方程的解:

  • 0=(xx0)f(x0)+f(x0)0=(x-x_0)*f^{'}(x_0)+f(x_0)

我们将新求得的点的xx坐标名为x1x_1,通常x1x_1会比x0x_0更接近方程f(x)=0f(x)=0的解。因此我们现在利用x1x_1开始下一轮迭代。迭代公式可以简化为下面表示:

  • xn+1=xnf(xn)f(xn)x_{n+1}=x_n-\frac{f(x_n)}{f^{'}(x_n)}
Leetcode 69:Sqrt(x)(超详细的解法!!!)

对于本题我们要求解的就是x2=nx^2=n的解,也就是f(x)=x2nf(x)=x^2-n,对应的f(x)=2xf^{'}(x)=2x

  • xi+1=xixi2n2xi=xi2+n2xi=xi+nxi2x_{i+1}=x_i-\frac{x_i^2-n}{2x_i}=\frac{x_i^2+n}{2x_i}=\frac{x_i+\frac{n}{x_i}}{2}
class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        res = x
        while res**2 > x:
            res = (res + x//res)//2
            
        return res

reference:

https://zh.wikipedia.org/wiki/牛顿法

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

相关文章: