前言:如何在在一个有序数组中找到一个确定的元素,对于不了解二分查找的人第一个想法就是遍历数组,直到找到该元素。但是对于一个训练有素的你来说第一个想法一定是二分查找,那么什么是二分查找呢?,二分查找的关键是什么呢?
最后会有3个leetcode上关于二分查找的基础题
目录
int left=0,right=n-1;
int mid;
while(left<=right){
mid=((right-left)>>1)+left;
if(nums[mid]==target){
return mid;
} else if(nums[mid]>target){
right=mid-1;
}else if(nums[mid]<target){
left=mid+1;
}
}
1 :二分查找与二分查找的关键
二分查找就是通过不断缩小左右边界的范围,直到找到中间元素与目标元素相等,并返回此时中间元素的下标
首先,我们需要两个指向左边界和右边界的变量left,right,以及代表中间元素的变量mid
int left=0;
int right=arrSize-1;
int mid;
其次我们需要中间元素的下标
mid=left+((right-left)<<1)+left;//这句代码相当于
//mid=left+(right-left)/2+left 但是运行速度快
//不用(left+right)/2是因为防止溢出,当left和right都是int值的一半的时候,加一起会大于2^31-1
//int 是有符号的,所以会大于int的最大值会溢出,而left+(right-left)/2+left就不会溢出
然后,我们需要比较中间元素和目标元素target的大小关系,当中间元素等于目标元素是,返回中间元素的下标。当中间元素大于目标元素是,也就是是目标元素target在中间元素的左边,此时我们需要缩小右边界的范围为mid-1。同理当中间元素小于目标元素target时,我们需要缩小左边界的范围为mid+1;而每缩小一次边界,左边界与右边界的距离就会减少二倍,这就是二分查找的本质
if(arr[mid]==target){
return mid;
}
else if(arr[mid]>target){
right=mid-1;
}
else if(arr[mid]<target){
left=mid+1;}
而二分查找的关键就是中间元素与目标元素的大小关系和如何结束二分查找而大小关系上面已经说完了。一般来说,结束条件是根据题目来决定的但是一般分为下面两种
当while(left<right)时,结束的条件为 left=rigdt
当while(left<=right)是,结束的条件为left=right+1,也就是左边界的值大于右边界的值
第二种避免了当left和right指向同一个元素而那个元素就是目标元素target的情况
2: leetcode上的3个二分查找基础题
2.1:这个是最基础的,上面已经分析过了
2.2:
2.3:
先分析一下:插入的这个元素的位置应该在 (arr[pos-1],arr[pos] ],(2,3] 此时插入在arr[pos]处,也就是目标元素不在该数组里面,或者(arr[pos-1],arr[pos] ),(2,3)此时没有插入,也就是目标元素在该数组里面,将这两个条件与二分查找合并成一个条件是:在数组中找到第一个比目标元素大于或等于de中间元素的下标,我们可以利用二分查找无线逼近于这个元素