704. 二分查找
使用二分查找的前提是(1)数组为有序数组(2)数组中无重复元素
注意边界条件是 while(left <= right) 还是 while(left <right)
请参考代码随想录
https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html#%E6%80%BB%E7%BB%93
35. 搜索插入位置
运行成功。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int low=0;
int high=nums.size()-1;
int mid;
if(target > nums[high]) return (high+1);
if(target < nums[low]) return 0;
while(low <= high) {//ERROR:条件写错,这里是小于等于
mid = (low + high)/2;
if(nums[mid] == target) {
return mid;
}
else if(nums[mid] > target) {
high = mid - 1;
}
else if(nums[mid] < target) {
low = mid + 1;
}
}
return low;
}
};
要点
返回值究竟是low还是high
如果数组中没有target,那么跳出循环前的一步 mid=low=high
(1)如果 target>nums[mid], low=mid+1
target 的位置在右侧,正好是low
(2)如果 target<nums[mid],high=mid-1
target 的位置就是 mid 这个位置(这里有个隐含条件是 target 比 nums[mid-1] 大)。
34. 在排序数组中查找元素的第一个和最后一个位置
想法:数组nums是有序数组,且要求查找时间复杂度为 O(log n)。因此可以用二分查找,但是因为nums中元素重复,查找到的下标只有一个,所以设置left、right指针,分别往前往后找边界。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int low,high,mid;
low = 0;
high = nums.size()-1;
int tnum;
int tpos = -1;
while(low <= high) {
mid = (low + high)/2;
tnum = nums[mid];
if(target == tnum) {
tpos = mid;
break;
}
else if(target > tnum) {
low = mid + 1;
}
else if(target < tnum) {
high = mid - 1;
}
}
vector<int> ans;
if(tpos == -1) {
ans.push_back(-1);
ans.push_back(-1);
return ans;
}
int left = tpos,right = tpos;
while(nums[left] == target) {
left--;
}
left++;
while(nums[right] == target) {
right++;
}
right--;
ans.push_back(left);
ans.push_back(right);
return ans;
}
};
报错
Line 1037: Char 34: runtime error: addition of unsigned offset to 0x602000000430 overflowed to 0x60200000042c (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/…/lib/gcc/x86_64-linux-gnu/11/…/…/…/…/include/c++/11/bits/stl_vector.h:1046:34
8 / 88 个通过的测试用例
错误原因:数组下标越界,当满足 nums[0] == target时,进入循环,left-- = -1。下一个循环进入判断,nums[-1] 超出数组边界。
同理,nums[right]也要考虑 right不超过nums数组的大小。
while(nums[left] == target) {
left--;
}
left++;
修改如下图
int left = tpos,right = tpos;
while(left >= 0 && nums[left] == target) {
left--;
}
left++;
while(target < nums.size() && nums[right] == target) {
right++;
}
right--;
报错:解答错误
28 / 88 个通过的测试用例
这里是while写错了 while( right < nums.size() && nums[right] == target)
再次修改如下图
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int low,high,mid;
low = 0;
high = nums.size()-1;
int tnum;
int tpos = -1;
while(low <= high) {
mid = (low + high)/2;
tnum = nums[mid];
if(target == tnum) {
tpos = mid;
break;
}
else if(target > tnum) {
low = mid + 1;
}
else if(target < tnum) {
high = mid - 1;
}
}
vector<int> ans;
if(tpos == -1) {
ans.push_back(-1);
ans.push_back(-1);
return ans;
}
int left = tpos,right = tpos;
while(left >= 0 && nums[left] == target) {
left--;
}
left++;
while(right < nums.size() && nums[right] == target) {
right++;
}
right--;
ans.push_back(left);
ans.push_back(right);
return ans;
}
};
运行成功