题目描述:
实现 int sqrt(int x)
函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
方法一、二分法:
很容易想到,所以在此不再啰嗦。
class Solution {
public int mySqrt(int x) {
int l=1,r=x;
int mid=(l+r)/2;
while(l<=r){
System.out.println("mid="+mid+" l="+l+" r="+r);
if(mid==x/mid)
return mid;
else if(mid>x/mid)
r=mid-1;
else
l=mid+1;
mid=(l+r)/2;
}
return mid;
}
}
方法二、牛顿迭代法:
名字看上去挺高大上的,网上各种讲解也看的稀里糊涂,后来看了大量别人写的博客再加上自己思考了一下,突然就明白了,发现也就那么回事。
这个题目的本质是让你求平方根,比如求x^2=t ,我们可以设一个函数f(x)=x^2- t ,令f(x)=0,很明显解x就是t的平方根,在图里表示为与X轴的交点横坐标。而我们要做的就是求出这个交点,手段是取图像上一个初始点(t,f(t)),作它的切线,切线与X轴交点横坐标为X0,接下来我们又作(X0,f(X0))的切线,有没有发现,我们作的切线再逐渐向左偏,切线与X轴的交点也慢慢接近图像与X轴的交点,一直重复以上作切线过程,最后它们会无限逼近,到最后f(Xn)近似等于0(i从0到n),那么我们就可以认为Xn就是要求的平方根。
平方根的具体过程如下:
1、题目要求的是x的平方根,所以t =x,同时我们假设x0开始等于x;
2、如上图所示,过点(x0,f(x0))做曲线的切线 ,切线方程是y1-f( x0 )=f(x0)' ( x1 - x0 ) ,令y1=0,解得x1=x0 / 2+t / (2*x0)
3、接下来重复2,即过点(x1,f(x1))做曲线的切线,切线方程是y2-f(x1)=f(x1)'(x2-x1) ,令y2=0,解得x2=x1 / 2 +t /(2*x1)
接着重复2,一直到 f(xn) 趋向于0,而f(xn)=xn^2-t=0,所以最后近似解就是xn
可以看出递推方程:X[i]=X[i-1]/2 + t/(2 * X[i-1])
class Solution {//牛顿迭代法,f(x)=x^2-t
public int mySqrt(int x) {
double t=(double)x;//(double)可以省
double x0=x;
x0=x0/2+t/(2*x0);
while(Math.abs(x0*x0-t)>0.00001)
x0=x0/2+t/(2*x0);
return (int)x0;//double 转int类型必须使用强制类型转化
}
}