先看题目:
初次接触这道题比较难想到可以采用二分查找的思想去做,但只要能想到这一点按理说就不会很困难。首先并不是简单的二分查找,它涉及到如果在我们的数组中找不到target值,那么当二分循环left <= right结束是,left或right的值会指向我们的target应该在数组中的位置。
并且这道题其实甚至不需要构造数组,刚开始我通过构造vector去进行二分查找,但实际上数组的范围就是近似的从0到x的递增区间,在这个区间里寻找某个数的平方是target值,如果找不到,则返回left或right作为结果。
先上错误答案:
class Solution {
public:
int mySqrt(int x) {
if(x == 0 || x == 1) return x;
vector<int> nums;
for(int i=0; i<=x/2; ++ i){
nums.push_back(i);
}
for(auto &i : nums){
i = i * i;
}
int left = 0, right = nums.size() - 1;
int mid = 0;
while(left <= right){
mid = left + (right - left) / 2;
if(nums[mid] == x) return mid;
else if(nums[mid] > x) right = mid - 1;
else left = mid + 1;
}
return right;
}
};
这里首先,使用了数组,浪费空间没有必要。其次还不是将数组元素单独计算平方,而是将每个元素转换为平方值,本身这道题数据范围比较大,再平方很容易越界。最后由于同样的原因,建议不要使用int变量而去使用long long会比较好。
最后是正确答案:
class Solution {
public:
int mySqrt(int x) {
if(x == 0 || x == 1) return x;
long long left = 0, right = x - 1;
long long mid = 0;
while(left <= right){
mid = left + (right - left) / 2;
long long t = mid * mid;
if(t == x) return mid;
else if(t > x) right = mid - 1;
else left = mid + 1;
}
return right;
}
};