思路一:二分 O(logn)
class Solution {
public:
int mySqrt(int x) {
//left 小于等于 right 大于 return left
int left = -1, right = (1 << 16);
while (left + 1 < right) {
int mid = left + (right - left) / 2;
if ((long long)mid * mid <= x) left = mid;
//加上(long long)
else right = mid;
}
return left;
}
};
易错点:当x值较大值,mid*mid可能会越int的界,因此要加上类型转换(long long)mid * mid!!!
思路二:转换到别的函数
思路:「袖珍计算器算法」是一种用指数函数和对数函数代替平方根函数的方法。我们通过有限的可以使用的数学函数,得到我们想要计算的结果。
class Solution {
public:
int mySqrt(int x) {
int ans = exp(0.5 * log(x));
return ((long long)(ans + 1) * (ans + 1) <= x) ? ans + 1 : ans;
//加上(long long)
}
};
易错点
1.e^x写法: exp(x); ln(x)写法:log(x)
2. 由于计算机无法存储浮点数的精确值(浮点数的存储方法可以参考 IEEE 754,这里不再赘述),而指数函数和对数函数的参数和返回值均为浮点数,因此运算过程中会存在误差。因此在得到结果的整数部分ans 后,我们应当找出ans 与ans+1 中哪一个是真正的答案!!!
3. 当x为int的最大值时,(ans + 1) * (ans + 1) 可能会越int的界,因此,要加强制类型转换!!!
思路三:牛顿迭代法
leetcode官方解释在这
class Solution {
public:
int mySqrt(int x) {
//牛顿迭代法 double
if (!x) return 0;
double ans = x;
double pre = x;
do {
pre = ans;
ans = (x + ans * ans) / (2 * ans);
}while (pre - ans > 1e-7);
return ans;
}
};
易错点
1:x==0要特殊判断!!!
2:用do while() 否则第一次就进不去循环!!!