1. 程式人生 > >Leetcode 69:Sqrt(x)(超詳細的解法!!!)

Leetcode 69:Sqrt(x)(超詳細的解法!!!)

實現 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) 零點的 x 0 x_0 ,計算相應的 f ( x
0 ) f(x_0)
和切線斜率 f ( x 0 ) f^{'}(x_0) (這裡 f f^{'} 表示函式 f f 的導數)。然後我們計算穿過點 ( x 0 , f ( x 0 ) ) (x_0,f(x_0)) 並且斜率為 f ( x 0 ) f^{'}(x_0) 的直線和 x x 軸的交點 x x 座標,也就是求如下方程的解:

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

我們將新求得的點的 x x 座標名為 x 1 x_1 ,通常 x 1 x_1 會比 x 0 x_0 更接近方程 f ( x ) = 0 f(x)=0 的解。因此我們現在利用 x 1 x_1 開始下一輪迭代。迭代公式可以簡化為下面表示:

  • x n + 1 = x n f ( x n ) f ( x n ) x_{n+1}=x_n-\frac{f(x_n)}{f^{'}(x_n)}

對於本題我們要求解的就是 x 2 = n x^2=n 的解,也就是 f ( x ) = x 2 n f(x)=x^2-n ,對應的 f ( x ) = 2 x f^{'}(x)=2x

  • x i + 1 = x i x i 2 n 2 x i = x i 2 + n 2 x i = x i + n x i 2 x_{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

如有問題,希望大家指出!!!