题目
分析 & 代码
第一想法是从1开始一个一个去试,这种想法比较naive,所以比较慢
需要注意的就是base开成long long的类型,不然会产生溢出
class Solution {
public:
int mySqrt(int x) {
if (x == 0) return 0;
long long base = 1;
for (; base * base <= x; ++base) {
if ((base + 1) * (base + 1) > x)
break;
}
return base;
}
};
跑了16ms 并不是最好的做法
换种思路,一个数n,它的方根只可能在1到n之间的某个数,而这些数是有序的,所以很容易联想到二分。
从1到n的范围,进行二分。具体的二分逻辑不难推出来,需要注意的就是最后return的值应该是右边界,原因在于跳出循环的时候,l是大于r的,而这里求的根是需要做向下取整的,所以应该是r而不是l
代码如下:
class Solution {
public:
int mySqrt(int x) {
if (x == 0) return 0;
int l = 1, r = x, mid;
while (l <= r) {
// 避免溢出
mid = l + (r - l) / 2;
// 除法避免溢出
if (x / mid > mid) l = mid + 1;
else if(x / mid == mid) return mid;
else r = mid - 1;
}
return r;
}
};
这次就只跑了0ms,比之前的方法提高不少