给定一个非负整数 x ,计算并返回 x 的平方根,即实现 int sqrt(int x) 函数。
正数的平方根有两个,只输出其中的正数平方根。
如果平方根不是整数,输出只保留整数的部分,小数部分将被舍去。
思路一:暴力破解
对于这个题,首先能想到的就是通过暴力解法来计算,对于所有i∈[1,x]来说,存在以下情况:
x/i=i --> i就是x的平方根,直接返回i
x/i>i --> i小于x的平方根,需要i++
x/i<i --> i大于x的平方根,后面就不需要遍历了,直接返回i-1
class Solution {
public int mySqrt(int x) {
if(x==0){
return 0;
}
int i=1;
while(i<=x){
if(x/i>i){
i++;
}
else if(x/i<i){
break;
}
else{
return i;
}
}
return i-1;
}
}
之所以这里不使用乘法是因为要防止数值过大导致溢出,而且这里要注意分母不能为0
思路二:二分查找
二分查找是暴力破解的一种优化,能够更快的找到符合要求的数
class Solution {
public int mySqrt(int x) {
int index=-1, left=1, right=x;
while(left<=right){
int mid=left+(right-left)/2;
if(mid*mid<=x){
index=mid;
left=mid+1;
}else{
right=mid-1;
}
return index;
}
}
思路三:牛顿迭代
对于i²=x来说,同时意味着i=x/i,这个时候我们计算(x/i+i)/2就得到了i的均值,但是这个值不一定满足i=x/i的要求,这个时候就需要进行迭代
class Solution {
public int mySqrt(int x) {
if(x==0){
return 0;
}
return (int)sqrt(x, x);
}
public double sqrt(double i, int x){
double res = (i + x/i)/2;
if(res==i){
return i;
}else{
return sqrt(res,x);
}
}
}