二分详解

92 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

二分

二分思想

 二分的思想很简单,就是对于一个有序的数组,要求有序(后一个数大于等于前一个数或是小于等于前一个数)不一定要求单调。
 取位置为 mid = (l + r) >> 1 的数判断该数是大于你要找的数x还是小于你要找的数x。如果是大于,就去left去找。如果是小于就去right中去找
 整体的思想就这么简单,但是二分难点是在于边界点的处理。对于二分边界点处理方法的不同,把二分分为两个模板

二分模板

image.png

橙色点情况

 如果是要根据求橙色点值的位置,mid的值有三种情况
  ①:如果mid的值 < x ,说明mid 的位置在橙色点的左边 l = mid + 1
  ②:如果mid的值=x,说明mid的位置可能是橙色点,也可能在橙色点左边 l = mid
  ③:如果mid的值 > x, 说明mid的位置在橙色点右边 r = mid - 1

int bssearch1(int q[], int l, int r, int x){
    int mid;
    int i = l, j = r;
    while(i < j){
        mid = (l + r + 1) >> 1;
        if(q[mid] <= x) l = mid;  //将情况1,2结合
        else r = mid - 1;
    }
    return q[l];
}

蓝色点情况

 如果是要根据求蓝色点值的位置,mid的值有三种情况
  ①:如果mid的值 < x ,说明mid 的位置在蓝色点的左边 l = mid + 1
  ②:如果mid的值=x,说明mid的位置可能是蓝色点,也可能在蓝色点右边 r = mid
  ③:如果mid的值 > x, 说明mid的位置在蓝色点右边 r = mid - 1

int bssearch2(int q[], int l, int r, int x){
    int mid;
    int i = l, j = r;
    while(i < j){
        mid = (l + r) >> 1;
        if(q[mid] >= x) r = mid; //将情况2,3结合
        else l = mid + 1;
    }
    return q[l];
}

注意:橙色点情况,mid值要向上取整。蓝色点情况,mid要向下取整。否则会出现死循环。这块也是二分的难点所在。