原题链接:https://leetcode-cn.com/problems/sqrtx/
题目:
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。
思路:
二分法找到最接近的那个整数。
思路很简单。
- 对于x取半,将这个半值mid的平方与x进行比较
- 如果相等,则返回
- 如果小于x,说明目标值在mid的右半部分
- 如果大于x,则说明在mid的左半部分
- 跳出循环的部分:假设找到目标值,则该值的平方小于x,且该值加1的平方大于x
class Solution {
public:
int mySqrt(int x) {
if (x == 0 || x == 1) {
return x;
}
int left = 0;
int right = x;
int mid = x/2;
while(1) {
//long long res = mid * mid;
if ((long long)mid * mid == x) {
return mid;
} else if ((long long)mid * mid > x) {
right = mid;
mid = (left + mid) / 2;
} else {
if ((long long)(mid + 1) * (mid + 1) > x) {
return mid;
}
left = mid;
mid = (mid + right) / 2;
}
}
return mid;
}
};
写的有点繁琐,看了下别人写的二分,改进了一下。
其实不难发现自己写的二分其实二分的不够彻底,没有把区间分到最后,中间还增加了很多关于平方值的判断,比较多余。
该二分就是最后把区间给确定了,需要注意的是左边界值和右边界值的改变,这样才能够跳出循环。
class Solution {
public:
int mySqrt(int x) {
if (x == 0 || x == 1) {
return x;
}
int left = 0;
int right = x;
int res;
while(left <= right) {
int mid = (left + right) / 2;
if ((long long)mid * mid <= x) {
res = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return res;
}
};
还有其他运用数学思想的解法比如牛顿迭代,找平方根更快。