首页 > 技术文章 > 每日一题:二分查找

fdbwymz 2020-12-02 19:58 原文

二分查找有很多细节,细节中藏着魔鬼

框架是while 加 if

细节在于退出while循环的条件,

空区间,值不存在特殊情况会返回什么。

1.建议对于所有区间使用左闭右开的习惯,即[ left , right ),结束时left一定与right重合

2.取中点时小心值溢出。

学习自知乎 https://www.zhihu.com/question/36132386?sort=created

核心思想是三个区间[ left0,left) [left,right) [ right, right0)

while循环时始终满足

1. 搜索区间[ left, right  )不为空 。

2. 搜索区间[ left0 , left )所有元素小于 target

3. 搜索区间[ right, right0) 所有元素大于等于 target

 

 

\

最终 left == right, 左边区间中所有值小于 target ,右边区间中所有值大于等于target。

因此返回 left 下标,就是返回第一个出现的target 或者第一个比 target 大的数

一、target左边界的二分查找

int binary( int [] sums, target )
   { int left = 0;
      int right = sums.length;
      while( left<right )
        {mid = left + (right - left) /2;
          if (sums[mid] < target)
              left = mid + 1;
          else
              right = mid ; 
          }
        return left;
      }
          

 返回值的问题

当target不存在时,返回大于的第一项

当target过大时,返回最后一项的后一位(越界问题)

当target过小时,返回第一项

二、STL库函数

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

推荐阅读