复杂的二分查找
二分查找是很经典的算法,也是很少代码能写出来的,但是,由于几个变式,导致它很容易出错。下面把我总结的模版给出来,以后解释。
1 package DataStructure; 2 3 public class BSearchTest { 4 5 static int binarySearch(int[] a, int x){ 6 if(a==null) //防御性编程 7 return -2; 8 if(a.length == 0) 9 return -1; 10 int mid=0 , l=0, r=a.length-1; 11 while(l < r){ 12 mid = l + (r-l+1)/2; // A : C加1时不加,C减1时加1 13 if(a[mid] < x) // B : 将目标落到一个区域,如果求区间 加等号,如果求边界不加等号 14 l = mid; // C 15 else 16 r = mid - 1; // C :一定总是差1,l+1, r-1 17 } 18 if(a[l] < x) // D : 判断是否超出答案区域,==号用于求区间,<号用于求边界 19 return l; // E : 返回哪个值,应该和目标区域边界相同 20 else 21 return -1; 22 } 23 /* 24 * 25 * 目标区域B,即要确定每次二分的过程,要保证所求的元素必然不在被排除的元素中 26 1)二分查找元素key的下标,如无 return -1 27 2)二分查找返回key(可能有重复)第一次出现的下标,如无return -1 (区间值) 28 3)二分查找返回key(可能有重复)最后一次出现的下标,如无return -1 29 第一步,定求区间值 30 定B,要加等号 31 定D,要加等号 32 第二步,定求最左边还是最右边,即当相等时 查左边还是查右边 33 第三步,如求左边,定C上部分,即相等时 r=mid 34 根据C定B的条件,即要让落在左边,则a[mid]要 大于 x 35 根据C定A,即左边不加1 36 定E 判断和返回 r 37 38 //4)二分查找返回刚好小于key的元素下标,如无return -1 (边界值) 39 //5)二分查找返回刚好大于key的元素下标,如无return -1 40 第一步,定求边界值 41 定了B、D无等号 42 第二步,定求上界,即第一个大于x的数, 定B ,目标是只找比x大的区域 a[mid]>x 43 定C,r=mid,要让mid大,只能找左边 44 定A,左边时不加1 45 定E,判断和返回目标区域的值 46 定D,大于才是答案 47 48 49 */ 50 public static void main(String[] args){ 51 int[] a = {2, 3, 3, 3, 5, 7, 11, 11, 13, 17}; 52 int x = 3; //4 53 System.out.println(binarySearch(a, x)); 54 } 55 }