50.Sqrt(x)(二分)

Implement int sqrt(int x).

Compute and return the square root of x.

转自:http://blog.csdn.net/doc_sgl/article/details/12404971

实际面试遇到的题目可能不是对一个整数开方,而是对一个实数。方法和整数其实是一致的,只是结束条件换成左界和右界的差的绝对值小于某一个epsilon(极小值)即可。在C++中我们需要通过两个数的绝对值差小于某个极小值来判断两个double的相等性。实际上两个double因为精度问题往往是不可能每一位完全相等的。

1. 二分法:

这道题一看到函数的定义int sqrt(int x)都是int就高兴了,直接二分吧。但是要注意,即使用long long都TM越界,还要用unsigned long long。最后返回值还要再检查一下。

int sqrt(int x) {  
        // Start typing your C/C++ solution below  
        // DO NOT write int main() function  
        unsigned long long begin = 0;  
        unsigned long long end = (x+1)/2;  
        unsigned long long mid;  
        unsigned long long tmp;  
        while(begin < end)  
        {  
            mid = begin + (end-begin)/2;  
            tmp = mid*mid;  
            if(tmp==x)return mid;  
            else if(tmp<x) begin = mid+1;  
            else end = mid-1;  
        }  
        tmp = end*end;  
        if(tmp > x)  
            return end-1;  
        else  
            return end;  
    }

2. 牛顿迭代法

50.Sqrt(x)(二分)

为了方便理解,就先以本题为例:

计算x2= n的解,令f(x)=x2-n,相当于求解f(x)=0的解,如左图所示。

首先取x0,如果x0不是解,做一个经过(x0,f(x0))这个点的切线,与x轴的交点为x1

同样的道理,如果x1不是解,做一个经过(x1,f(x1))这个点的切线,与x轴的交点为x2

以此类推。

以这样的方式得到的xi会无限趋近于f(x)=0的解。

判断xi是否是f(x)=0的解有两种方法:

一是直接计算f(xi)的值判断是否为0,二是判断前后两个解xi和xi-1是否无限接近。

经过(xi, f(xi))这个点的切线方程为f(x) = f(xi) + f’(xi)(x - xi),其中f'(x)为f(x)的导数,本题中为2x。令切线方程等于0,即可求出xi+1=xi- f(xi) / f'(xi)。

继续化简,xi+1=xi- (xi2- n) / (2xi) = xi- xi/ 2 + n / (2xi) = xi/ 2 + n / 2xi= (xi+ n/xi) / 2。

有了迭代公式xi+1= (xi+ n/xi) / 2,程序就好写了。关于牛顿迭代法,可以参考wikipedia以及百度百科

class Solution {
public:
    int mySqrt(int x) {
        if (x ==0)  
            return 0;  
        double pre;  
        double cur = 1;  
        do  
        {  
            pre = cur;  
            cur = x / (2 * pre) + pre / 2.0;  
        } while (abs(cur - pre) > 0.00001);  
        return int(cur);  

    }
};
float InvSqrt(float x)  
{  
    float xhalf = 0.5f*x;  
    int i = *(int*)&x; // get bits for floating VALUE  
    i = 0x5f375a86- (i>>1); // gives initial guess y0  
    x = *(float*)&i; // convert bits BACK to float  
    x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy  
    return x;  
}

原文链接: https://www.cnblogs.com/qiaozhoulin/p/4574728.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/217652

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午9:53
下一篇 2023年2月13日 上午9:53

相关推荐