整数:
同时注意右移运算>>1与整除/2不同。右移运算是向下取整,整数除法是向零取整:
-5 / 2 = -2
,5 / 2 = 2
。 这表明除二是向零取整-5 >> 1 = -3
,5 >> 1 = 2
。这表明右移一位是向下取整
右移一位和除二的区别_FlushHip-CSDN博客_右移一位
模板一:
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。
l+r >> 1向下取整,若l=mid,mid可能刚好为 l.5,mid取整刚好为l就陷入死循环了。
为什么此时l+r不加1,因为l的执行条件是l=mid+1。即使l=1,r=2,mid=1。l会在mid的基础上加1,从而跳出循环。
模板二:
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。
为什么此时l+r要加1,因为l执行的条件是l=mid。当l=1,r=2时,如果mid=(l+r)>>1,那么mid=1,此时l=mid仍要循环就死循环了。所以要向上加1。
浮点数
double bsearch(double l, double r) {
const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求, 一般比所求精度高2位
while (r - l > eps) {
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}
确定好精度eps,以l+eps<r为循环条件。若保留k位小数,则eps=10的(-k+2)次方
力扣模板题:
注意:右边界应该从nums.length开始
class Solution {
public int search(int[] nums, int target) {
int l=0;
int r=nums.length;
while(l<r){
int m=l+r>>1;
if(nums[m]<target) l=m+1;
else if(nums[m]>target) r=m;
else return m;
}
return -1;
}
}