题目及测试
package pid069;
/*x 的平方根
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
*/
public class main {
public static void main(String[] args) {
int[] testTable = {2147395599,9,4};
for (int i=0;i<testTable.length;i++) {
test(testTable[i]);
}
}
private static void test(int ito) {
Solution solution = new Solution();
int rtn;
long begin = System.currentTimeMillis();
System.out.println(ito);
rtn = solution.mySqrt(ito);//执行程序
long end = System.currentTimeMillis();
System.out.println(rtn);
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(成功,43ms,较快)
首先先声明,举例,一个数字为100,200,3000,长度为3,4,他们的平方根在10-99之间,即长度为2,可以得到平方根长度为(length+1)/2
所以可以得到一个数字的平方根上下限的100,1000,然后使用二分查找得到对应的平方根。
注意:是平方根的话,是if(x>=mid*mid&&x<(mid+1)*(mid+1)) 在一个区间内
二分查找的话,能够改进的就是初始上下限的问题,设置上限作用较大(位数少了一半),设置下限作用较小,但是也还不错,是优化
package pid069;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Solution {
public int mySqrt(int x) {
int length=String.valueOf(x).length();
//10000(5 100) 100(3 10) 100-9999 (3-4 10-99) 10000-999999(5-6 100-999)
int sqrtLength=(length+1)/2;
double begin=(int)Math.pow(10, sqrtLength-1);
double end=(int)Math.pow(10, sqrtLength);
if(x==(begin*begin)){
return (int)begin;
}
if(x>=(end*end)){
return (int)end;
}
while(true){
double mid=(double)(int)((begin+end)/2);
if(x>=mid*mid&&x<(mid+1)*(mid+1)){
return (int)mid;
}
if(x>=(mid+1)*(mid+1)){
begin=mid+1;
}
else{
end=mid-1;
}
}
}
}
解法2(别人的)
这个题目的本质是让你求平方根,比如求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 ) - t,令y1=0,解得x1=x0 / 2+t / (2*x0)
3、接下来重复2,即过点(x1,f(x1))做曲线的切线,切线方程是y2-f(x1)=f(x1)'(x2-x1) - t ,令y2=0,解得x2=x1 / 2 +t /(2*x1)
接着重复2,一直到 f(xn) 趋向于0,而f(xn)=xn^2-t=0,所以最后近似解就是xn
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类型必须使用强制类型转化
}
}