二分查找基础模板

用一个例子体会二分查找基本思想,理解开区间和闭区间的区别,以及>=,>,<=,<这四种情况下如何解决,写出二分基本模板


问题

给定一个有序数组和元素x,返回其中第一个大于等于元素x的下标,如果都小于x,则返回其数组长度,例如数组num = [5,7,7,8,8,10],返回第一个>=8的下标。


一、解决模板

1.闭区间

      l和r分别指向左右边界,设l = 0,r = num.size() - 1,mid =(l + r)/ 2向下取整,为防止溢出,可以令mid = l + (r -l)/ 2。

      当mid < 8 时,需要令l=mid+1,为什么不是等于mid呢,因为mid<8时,代表从l到mid这段上的元素都是小于8的,这是闭区间,所以我们需要从mid+1开始,如果l=mid,那么此时就变成左开右闭区间了,因此下一步就要要将l = mid+1,这也同时说明,l-1指向的一定小于8;当mid>=8时,代表mid到r都是大于等于8的,剩下不确定的区间为[l,mid-1],所以将r = mid - 1,同时说明,r+1一定大于等于8。

      当循环结束后,r+1始终大于等于8,所以r+1就是我们要寻找的答案,由于循环结束r+1 = l,所以答案也可以用l来表示。

      代码实现就如下:

int left =  0;
int right = num.size() - 1;//闭区间[left,right]
while(left <= right){//区间不为空
  int mid  = left + (right - left) / 2;
  if(num[mid] < 8){
    left = mid + 1;//[mid+1,right]
  }
  else{//[left,mid-1]
    right = mid - 1;
  }
}
return left;

2.左闭右开区间

       l指向左边界,r指向右边界加1,设l = 0,r = num.size(),mid =(l + r)/ 2向下取整,为防止溢出,可以令mid = l + (r -l)/ 2。

      当mid < 8 时,代表l到mid都是小于8,左边还是闭区间,因此下一步就要要将l = mid+1,这也同时说明,l-1指向的一定小于8;当mid>=8时,代表mid到r都是大于等于8的,剩下不确定的区间为[l,mid),所以将r = mid ,同时说明,r一定大于等于8。

      最后当l等于r时,代表区间为空了,循环结束,此时l和r都是指向答案的

      代码如下:

int left =  0;
int right = num.size();//左闭右开区间[left,right)
while(left < right){//区间不为空
  int mid  = left + (right - left) / 2;
  if(num[mid] < 8){
    left = mid + 1;//[mid+1,right)
  }
  else{//[left,mid)
    right = mid;
  }
}
return left;

3.开区间

      l指向左边界-1,r指向右边界加1,设l = -1,r = num.size(),mid =(l + r)/ 2向下取整,为防止溢出,可以令mid = l + (r -l)/ 2。

      当mid < 8 时,代表l到mid都是小于8,左边还是开区间,因此下一步就要要将l = mid,这也同时说明,l指向的一定小于8;当mid>=8时,代表mid到r都是大于等于8的,剩下不确定的区间为[l,mid),所以将r = mid ,同时说明,r一定大于等于8。

      最后当l+1等于r时,代表区间为空了,循环结束,此时l+1和r都是指向答案的

      代码如下:

int left =  -1;
int right = num.size();//左闭右开区间(left,right)
while(left+1 < right){//区间不为空
  int mid  = left + (right - left) / 2;
  if(num[mid] < 8){
    left = mid;//(mid,right)
  }
  else{//(left,mid)
    right = mid;
  }
}
return right;

二、>= > < <=四种解决方式

如果题目要求的不是返回大于等于而是其他的呢,那么我们又该如果解决

     我们需要知道,不管是大于,还是小于,还是小于等于,这四种类型都是可以互相转换来的,我们都可以通过大于等于来转换过来。

      对于大于来说,设大于的target为x,我们可以把他看成是大于等于x+1,对于整数来说;对于小于来说,可以看成大于等于x的那个数的左边的那个数;对于小于等于,我们可以看成大于x的那个数左边的那个数

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值