1. 程式人生 > >LeetCode演算法題69:x的平方根解析

LeetCode演算法題69:x的平方根解析

實現 int sqrt(int x) 函式。
計算並返回 x 的平方根,其中 x 是非負整數。
由於返回型別是整數,結果只保留整數的部分,小數部分將被捨去。
示例1:

輸入: 4
輸出: 2

示例2:

輸入: 8
輸出: 2
說明: 8 的平方根是 2.82842..., 
     由於返回型別是整數,小數部分將被捨去。

暴力法遍歷整個實數集就不說了,雖然簡單,但是時間複雜度太高。介紹兩種演算法求平方根,一種是二分查詢,既然暴力法可以遍歷從0到其本身,那麼相當於查詢一個數,所以查詢有序數列一個很好的節省時間的方法就是二分法。一開始設定左右邊界,左邊界為1,右邊界為x(數字本身),這裡從1開始是為了程式的簡單,1和0都直接返回數字本身。然後只要左邊界還小於右邊界就一直查詢,查詢過程是這樣的,首先求取左右邊界的中值,然後計算中值平方,如果中值平方大於目標數字,那說明偏大,將右邊界設定為中值,(這裡是向下取整求取一個近似值,所以這個演算法中求的是大於目標數字的那個值,最後返回的是右邊界減1),如果中值小於等於目標數字,那麼左邊界設定為中值加1。最後返回右邊界減一。
C++原始碼:

class Solution {
public:
    int mySqrt(int x) {
        if (x <= 1) return x;
        int left = 1, right = x;
        while (left < right) {
            int mid = (left + right) / 2;
            if (x / mid >= mid) left = mid + 1;
            else right = mid;
        }
        return right -
1; } };

python的程式碼使用另一種求平方根的方法,就是使用牛頓迭代法。牛頓迭代法求平方根的迭代公式為:
a n + 1 =

a n ( a n 2 n ) / ( 2 a n ) &ThinSpace; . a_{n+1} = a_n - ({a_n^2} - n) / (2*a_n)\,.
所以只要用這個公式求出一個數,其平方不大於目標數則為所求。之所以可以這麼設定條件,是因為牛頓迭代法初值設定的很大時,一開始是從右向左收斂的,在精確值附近才會左右擺動,所以這裡都是整數,因此可以這樣設定條件。
python3原始碼:

class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        res = x
        while res * res > x:
            res = (res + x // res) // 2;	# 公式變形,只有用這個才不會發生錯誤
        return res

這個程式如果不太好懂可以把條件換成兩次迭代值的差小於某一閾值,這裡的話只要小於0.1即可求得最後值。
python3原始碼:

class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        if x == 0:
            return 0
        res = 1.0
        pre = 0.0
        while abs(res - pre) > 0.1:
            pre = res
            res = (pre + x / pre) / 2
            # res = pre - (pre * pre - x) / (2 * pre) #也可以
        return int(res)