69. Sqrt(x)
我的思路:
这题应该用牛顿迭代法就好了。
牛顿迭代法的伪码大概描述一下就是:
要求 sqrt(a)
x1=a/2,xn+1=(xn+axn)/2
直到 xn 与 xn+1 的差足够小。
在这里我直接取整返回。
我的代码:
class Solution {
public:
int mySqrt(int x) {
if(x == 0) {
return 0;
}
double t1 = x / 2.0;
double t2 = (t1 + x / t1) / 2;
while(fabs(t1 - t2) > 0.001) {
t1 = t2;
t2 = (t1 + x / t1) / 2;
}
return int(t2);
}
};
最快解法的代码:
class Solution {
public:
int mySqrt(int x) {
if(x<2) return x;
int y=x/2;
while(y>x/y) {
y=(y+x/y)/2;
}
return y;
}
};
应该说也是用的牛顿迭代法,但是相比浮点数运算,整数运算要快一点,所以速度会快一点。
但是我看了这个解法,并没有办法一下感受到这个解法的正确性,也就是while的条件为什么可以那么取,因此我决定证明一下。这里给出一个比较粗略的证明。注意一下,下面的除法都是c++的整数除法。
∵y=x/2
∴(x−1)2/4≤y2≤x2/4
显然我们可以看出
y2=O(x2)
,也就是当
x
足够大的时候,必定有
因此while的起始条件成立。
∵y>x/y
∴y+x/y<y+y
∴y 是递减的,因此是可以找到出口的
至于为什么这个出口是对的,应该要去看牛顿迭代法的证明吧。。。
x <script type="math/tex" id="MathJax-Element-13">x</script> 比较小的情况,应该枚举一下就可以得到正确性了。。。