笔试题83. LeetCode OJ (69)

来源:互联网 发布:淘宝实时访客软件 编辑:程序博客网 时间:2024/06/14 13:48

    Sqrt(x)

    没错,有几天没写LeetCode了,就遇上了sqrt函数的编写,这是不是很简单呢?于是我很快的想出了遍历的方法,但是马上又想到了若是一个最大的整数位测试用例呢?那么效率太低了吧,于是我以效率为出发点又想到了二分法,使用二分法自己测试了几个,感觉还可以,于是就提交了,代码如下:

class Solution{public:int mySqrt(int x){//二分法assert(x >= 0);//1.特殊情况if (x == 0 || x == 1){return x;}//2.一般情况int left = 0;int right = x;int mid = (left + right) / 2;while (mid*mid > x || (mid+1)*(mid+1) <= x){if (mid * mid > x){right = mid;}else if ( (mid + 1) * (mid + 1) <= x){left = mid;}mid = (left + right) / 2;}return mid;}};
测试用例卡在了2147395599上面,结果如下:



出现这种结果说明二分法还是不够优化,那么我们所能想到的办法还有什么呢?我感觉真的是想不出来,于是我在网上看了一些文章,将关于sqrt函数的问题,于是我找到了一种求解方法,利用到的思想是”牛顿迭代法快速寻找平方根“,其思想是利用高数中的思想:求 X^2 - a = 0 的根,这些思想若是没有学习过真的是想不出来的,我是参考一篇文章,所以最后我会将这篇文章贴出来,分享给大家。

使用牛顿迭代快速寻找平方根的思想,我们可以写出下列代码:

class Solution{public:int mySqrt(int x){//牛顿迭代法assert(x >= 0);if (x == 0 || x == 1){return x;}float val = x;   //最终float last;//保存上一个计算的值do{last = val;val = (val + x / val) / 2;} while (abs(val - last) > 0.01); //因为这个题的最终结果是整数,所以我们可以将精度提高点int ret = (int)val;if (ret*ret > x){return ret - 1;}else{return ret;}}};
这个函数最终被接收了,结果如下:


其实到这里还没完呢?有些人真的是大神,他们只要两步就可以求出一个数的平方根,他的思路我还没弄明白,因为源码是某游戏引擎的代码,不过这里还是将他的代码贴出来,跟大家分享一下:

class Solution{public:int mySqrt(int x){//数学大神根据牛顿迭代法来求推导出的神奇方法assert(x >= 0);if (x == 0 || x == 1){return x;}float tmp = x;float xhalf = 0.5f*tmp;int i = *(int*)&tmp;i = 0x5f375a86 - (i >> 1); // 这一步是关键tmp = *(float*)&i;tmp = tmp*(1.5f - xhalf*tmp*tmp);tmp = tmp*(1.5f - xhalf*tmp*tmp);tmp = tmp*(1.5f - xhalf*tmp*tmp);int ret = 1 / tmp;if (ret*ret > x){return ret - 1;}return ret;}};
这种方法是正确的,因为它是游戏引擎中的源码,所以不用验证都可以知道其正确性。

    我个人觉得这种类型的题真的是很吃数学功底,也道题很彻底的让我感受到了数学的强大,让我深受感触。下面我就给出我看过的文章的出处:参考文章

0 0
原创粉丝点击