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