在题目要求上没有看到说不能使用库函数,所以直接通过使用Math下的sqrt()方法就解决了,但是题目的本意肯定是希望能够自己实现sqrt的,而且返回的是int类型,所以最开始的想法就是,通过循环,re每次加1,求re使得re*re=x,或当re*re>x时,re-1即为所求,但是这样的效率太低了,当x的值很大时便会出现超时。
所以通过网上查看其他人的想法, 总结如下
有两种方法:1、二分法;2、牛顿迭代法
1、二分法
x的平方根肯定小于x/2+1,因此通过计算判断每次出去一半的值。
代码:
class Solution {
public int mySqrt(int x) {
if(x == 0)
return 0;
int head = 1;
int last = x/2+1;
while(head<=last){
int mid = (head + last)/2;
if(mid <= x/mid && (mid+1) > x/(mid+1))
return mid;
if(mid<x/mid)
head = mid+1;
else
last = mid-1;
}
return 0;
}
}
2、牛顿迭代法
基本思想是,x^2=n,可以构造函数f(x) = x^2-n,即找到f(x)=0的解。
如图所示,首先判断x0是否为f(x)=0的解,如果不是,则过(x0, f(x0))做f(x)的切线,与x轴的交点(x1,0),继续判断x1是否为所求解,以此类推,求得的xi会无限接近f(x)=0的解。
经过计算x1 = (x0+n/x0)/2,由此得到xi+1 = (xi+n/xi)/2。
所以代码为:
int sqrt(int x) {
if (x == 0)
return 0;
double tmp = 0;
double re = 1;
while (tmp != re)
{
tmp = re;
re = (re + x / re) / 2;
}
return int(re);
}
在java中,判断两个double数是否无限接近,使用==即可,java自动进行了处理。
在此题出,如果返回类型为double,将第二种方法中,进行简单的类型修改即可。
本文参考了以下两篇博客。
http://www.cnblogs.com/AnnieKim/archive/2013/04/18/3028607.html。
http://blog.csdn.net/linhuanmars/article/details/20089131