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;
}
};
运行成功

文章讲述了在有序数组中使用二分查找算法解决搜索插入位置和查找元素第一个/最后一个位置的问题,强调了边界条件的正确处理以及处理数组下标越界的情况。
758

被折叠的 条评论
为什么被折叠?



