二分查找简介
二分查找主要是用于有序序列的二段性的问题的,二段性指的是在数组或其他有序序列中(当然这个有序序列需要我们能够结合题目进行分析出来),某个元素的左边的元素小于它,右边的元素大于它,然后查找进行查找元素
朴素二分查找算法
这个算法的目的就是查找一个有序序列中有没有某个元素,直接查出来就行,就算有多个相同的元素只是需要返回其下标就可以了,不用管其他相同元素的下标
例题
题目链接

代码
cpp
int search(vector<int>& nums, int target) {
int left=0,right=nums.size()-1;
while(left<=right)
{
//int mid=(left+right)/2;
int mid=left+(right-left)/2; //right太大的时候需要与left相
if(nums[mid]<target) //加可能会溢出,所以用下面这种取中点的方式
{
left=mid+1;
}
else if(nums[mid]>target)
{
right=mid-1;
}
else return mid;
}
return -1;
}
这个可以作为模板来记忆,当然是理解性能记忆,类似的题目条件一换就可以了
求左右端点的二分查找算法
因为一个序列中可能存在多个相同的元素,这个序列是非递减的序列,这个题目需要用到求左右端点的二分查找算法
求左端点的二分查找算法
cpp
int find_mid(vector<int>& nums, int target)
{
int left = 0, right = nums.size() - 1;
while (left < right)
{
int mid = left + (right - left) / 2;
if (target >nums[mid])
{
left = mid + 1;
}
else
{
right = mid;
}
}
if (nums[left] == target)
{
return left;
}
else
{
return -1;
}
}
大致思路和朴素二分查找算法的思路大差不差,但是有一些细节需要解释,而且非常重要

查找右端点的二分查找算法
cpp
int find_mid(vector<int>& nums, int target)
{
int left = 0, right = nums.size() - 1;
while (left < right)
{
int mid = left + (right - left+1) / 2;
if (target >=nums[mid])
{
left = mid;
}
else
{
right = mid-1;
}
}
if (nums[left] == target)
{
return left;
}
else
{
return -1;
}
}
具体分析方法和上面的一样,就不多解释了
题目的代码
cpp
vector<int> searchRange(vector<int>& nums, int target) {
//查询左端点
if(nums.size()==0) return {-1,-1};
int left=0,right=nums.size()-1;
int begin=-1,end=-1;
while(left<right)
{
int mid=left+(right-left)/2;
if(target<=nums[mid])
{
right=mid;
}
else
{
left=mid+1;
}
}
if(nums[left]==target) begin=left;
else return {-1,-1};
//右边端点
left=0,right=nums.size()-1;
while(left<right)
{
int mid=left+(right-left+1)/2;
if(target>=nums[mid])
{
left=mid;
}
else
{
right=mid-1;
}
}
end=left;
return {begin,end};
}