二分法的研究

二分法的边界条件很重要,那么该边界条件是如何得到的呢?本文对这个问题给予简单的解答。

1. 二分法的中间值位置(主要研究向下取整,因为该操作符合C语言中整数除法的操作,另外向下取整得到的结果和如下结果相反)

  用数组a[0..3]表示含有4个元素的数组,假设left=0,right=3,那么middle=(left+right)/2=1(c语言),对应的元素是a[1];

  用数组b[0..2]表示含有3个元素的数组,假设left=0,right=2,那么middle=1,对应的元素是b[1];

  用数组c[0..1]表示含有2个元素的数组,假设left=0,right=1,那么middle=0,对应的元素是c[0];

  用数组d[0..0]表示含有1个元素的数组,假设left=0,right=0,那么middle=0,对应的元素是d[0];

  上面的结果画成图,可以得到如下图,可以看出二分法向下取整的坐标,如果数组是奇数长度,那么中间值是位于正中的位置;如果数组是偶数长度,那么中间值是位于正中偏左的位置。那么在用中间值划分区间时,可以将左半边划分为[left,middle-1],右半边划分为[middle+1,right]

  

2. 二分法处理的数据空间

  按照上面的划分方法,二分法处理的数据空间变化如下:

  7个元素-->3个元素

  6个元素-->3个元素或2个元素

  5个元素-->2个元素

  4个元素-->2个元素或1个元素

  3个元素-->1个元素

  2个元素-->1个元素或查找失败

  1个元素-->查找成功或查找失败

  可以看出,处理的边界就是while(left<=right)

3. 例题讲解

  LeetCode 69题 Sqrt(x)

  Implement int sqrt(int x).

  Compute and return the square root of x.

  该题用普通的遍历1到x来求平方根,算法复杂度是O(n),但是用二分查找的算法复杂度是O(logn),所以这里采用二分查找,具体的代码如下:

 1 int bs(long long x, long long left, long long right){
 2     if(left>right)return (left+right)/2;//没有整数根,所以用近似根
 3     long long middle=(left+right)/2;
 4     if(middle*middle==x)return middle;
 5     else if(middle*middle<x)return bs(x,middle+1,right);
 6     else return bs(x,left,middle-1);
 7 }
 8 
 9 int mySqrt(int x) {
10     return bs(x,1,x);
11 }
原文地址:https://www.cnblogs.com/gremount/p/6760677.html