问题:
Implement int sqrt(int x)
.
Compute and return the square root of x.
x is guaranteed to be a non-negative integer.
Example 1:
Input: 4 Output: 2
Example 2:
Input: 8 Output: 2 Explanation: The square root of 8 is 2.82842..., and since we want to return an integer, the decimal part will be truncate
① 暴力破解,超时。
public class Solution {
public int mySqrt(int x) {
if (x <= 0) return 0;
int res = 1;
for (int i = 1;i * i <= x ;i ++ ) {
if (i * i == x) {
res = i;
break;
}else{
res = i;
}
}
return res;
}
}
② 二分法,因为从1到sqrt(x)都是有序的,采用二分法可以更快的查找到结果。耗时3ms。
public class Solution {
public int mySqrt(int x) {
double diff = 0.01;//误差
int start = 0;//不能写成double,否则输入为5时结果错误
int end = x;
while(start <= end){
double mid = (end - start) / 2 + start;//定义为double类型,防止越界
if (Math.abs(mid *mid - x) <= diff) {
return (int)mid;
}else if(mid * mid + diff < x){
start = (int)mid + 1;
}else if(mid * mid + diff > x){
end = (int)mid - 1;
}
}
return end;//不存在该根值时,返回最接近根值的
}
}
另一种解法:
public class Solution {//4ms
public int mySqrt(int x) {
if (x < 0) {
return -1;
}
long start = 0;//long类型 防止越界
long end = x;
while (start + 1 < end) {
long mid = start + (end - start) / 2;
if (mid * mid == x) {
return (int) mid;
}else if (mid * mid < x) {
start = mid;
}else {
end = mid;
}
}
if (end * end == x) {
return (int) end;
}else {
return (int) start;
}
}
}
③ 使用牛顿迭代法求解:
给定一个正数a, 设其平方根为x,则有x^2=a,即x^2-a=0。设函数f(x)= x^2-a,则可得图示红色的函数曲线。在曲线上任取一点(x0,f(x0)),其中x0≠0那么曲线上该点的切线方程为
(1-1)
求该切线与x轴的交点得
(1-2)
因为1-2式中x0作为分母,所以在之前限定了一下初始值不要选0。那么得到的这个与x轴的交点其实是最终要求得的x的一次逼近,我们再以这个x基准继续迭代就可以求得更逼近的x,至于逼近到什么时候才算完,这个取决于你自己设定的精度。整个过程的迭代只需要几步就可以求得最终的结果。
代码如下:
public class Solution {//3ms
public int mySqrt(int x) {
if (x == 0) return 0;
double pre = 0;
double cur = 1;
while(Math.abs(cur - pre) > 0.00001){
pre = cur;
cur = x / (2 * pre) + pre / 2.0;
}
return (int)cur;
}
}