C++ 手動實現開平方根,立方根[LeetCode 69]


題目:

給你一個非負整數 x ,計算並返回 x 的 平方根 。
由於返回類型是整數,結果只保留 整數部分 ,小數部分將被 舍去 。
注意:不允許使用任何內置指數函數和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:
輸入:x = 4
輸出:2

示例 2:
輸入:x = 8
輸出:2
解釋:8 的平方根是 2.82842..., 由於返回類型是整數,小數部分將被舍去。

提示:
0 <= x <= 231 - 1

鏈接:https://leetcode-cn.com/problems/sqrtx

第一種思路是,牛頓迭代公式:

假設有一條曲線C,在曲線上面任選一點x0 = 1, 求的曲線的值為f(1), 即(1, f(1))為曲線上得一點。過點(1, f(1)), 作一條曲線C的切線,切線與X軸相交於點x1。同理使用x1求得x2、x3、x4......。所求得的一些列與X軸相交的點位曲線與X軸相交點得近視值。如設定某一誤差e,當x(n+1)-x(n) < e,則可認為x(n+1)是曲線的一個近視解。因為x(n+1)作為曲線的解誤差為可以接受的e。

其實,對於某個點,相對於曲線的切線方程是確定的,即為:f(x0) = f'(x0)(x - x0), 其中f'(x0)為切線的斜率。化簡即為x1 = x0 - f(x0)/f'(x0)。由此可得牛頓迭代公式為:

x(n+1) = x(n) - f(x(n))/f'(x(n));

要求根號2的近似值,可假設f(x) = x^2 - 2 = 0;即曲線x^2 -2 = 0的解即為根號2的值,然后根據上方公式不斷逼近解

代碼如下,既然返回結果為整數,那么不妨規定誤差為e=0.1,代碼如下:

class Solution {
public:
    int mySqrt(int x0) {
        if(x0==0)
            return 0;
        double x1=1,x2=0; //初始點選為x=1,當數值很大時,float不夠精確,
        double difference=x1>x2?x1-x2:x2-x1; //計算每次的誤差,正值
        int res=0;
        while(difference>0.1) //設定誤差小於0.1后得到結果
        {
            x2=x1-(x1*x1-x0)/(2*x1); //根據公式計算下一個點的橫坐標x2
            difference=x1>x2?x1-x2:x2-x1;//更新誤差
            x1=x2; //更新公式中最新的橫坐標到x1
        }
        res=floor(x2);
        return res;
    }
};

第二種思路是二分法,left=1,right=x,然后通過mid依次向結果靠近,left與right重合或交叉后停止,即為結果:

class Solution {
public:
    int mySqrt(int x) {
        if(x==0)
            return 0;
        int left=1,right=x;
        int mid;
        while(right-left>1)
        {
            mid=left+(right-left)/2;
            if(mid>x/mid) //如果當前mid平方比x大,那么在左區間
                right=mid;
            else            //反之,剩余情況認為在右區間
                left=mid;
        }
        return left;
    }
};

兩種做法內存占用相差不大

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM