1、题目
2、错误分析
class Solution {
public:
int search(vector<int>& nums, int target) {
int n=nums.size();
int left=0;
int right=n-1;
int mid=(right+left)/2;
while(target!=nums[mid] && left<right)
{
if(target>nums[mid])
left=mid+1;
else
right=mid-1;
mid=(right+left)/2;
}
if(target==nums[mid]){
return mid;
}
return -1;
}
};
上述为首次代码,显示通过,但是内存消耗高!
(1)变量n没有必要,直接调用size()-1赋值给right就可以;
(2)上述代码运行没有问题,即使当时并没有意识到开闭区间的问题,按照right=n-1,应该是[]闭区间,但是left<right判断条件就是在[)区间中寻找,因为mid(int相除,会丢弃小数位)会等left会取到左边,取不到右边,但是因为多问了一下,target此时是否还等于nums[mid],此时left被+1到了原本right的位置,就刚好补上了取不到right的隐藏bug.....解题思路并不清晰。。。
3、题解
(1)二分查找前提条件必须满足:排好序的+无重复元素;
(2)int/int,结果会丢弃小数位;
(3)正确认识一下,纠结的判断条件,当left<right,此时判断的区间是【left,right)左闭右开区间,是取不到right的值,因此开始right赋值就应该是nums.size(),没有-1(因为取不到),而在判断之后的right=mid;不需要-1,因为取不到;当left<=right,判断区间就是【left,right】,此时right=nums.size()-1,判断之后,right=mid-1;
(4)修正答案如下:(左闭右闭区间)
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size()-1;
while(left<=right){
//int mid=(left+right)/2;//避免right+left造成大数
int mid=left+(right-left)/2;//防止内存溢出(超出整数范围)
//int mid=left+((right-left)>>1);//右移等于除以2
if(target>nums[mid]){
left=mid+1;
}
else if(target<nums[mid]){
right=mid-1;
}
else
return mid;
}
return -1;
}
};
以下代码摘自“代码随想录”题解(左闭右开区间):
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
right = middle; // target 在左区间,在[left, middle)中
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,在[middle + 1, right)中
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};