JAVA实现二分查找
两次耻辱的面试,两次都是败在二分查找上。一次是处女面,一次是工作后的处女面,简直是标志性杯具...
分析原因,一个是怯场,一个是二分查找的边界处理确实容易遗漏。在自己的blog上留个记录。
网上查了查,主要参考这里的实现
鉴于二分查找对于本身没多大实际作用(平时有很多库函数供咱调用),也就是面试的时候用用,我把泛型的处理去掉了,对于递归版本略微重构了下。
有两点要注意
1. 二分查找迭代,两边的查找范围分别是low~mid-1 mid+1~high mid位置本次递归已经处理
2. 递归算法必须具备两个部分:初始情况和递归部分。二分的初始情况为low > high。low==high的情况也不用特殊处理,原因是此时mid == low ==high,直接对mid做判断足够。
递归版
// 递归版本
public static int searchRecursively(int[] data, int key) { if (data == null || data.length < 1) return -1; return doSearchRecursively(data, 0, data.length - 1, key); } private static int doSearchRecursively(int[] data, int low, int high,int key) { if (low > high) return -1; int mid = (low + high) / 2; if (key < data[mid]) { return doSearchRecursively(data, low, mid - 1, key); } else if (key > data[mid]) { return doSearchRecursively(data, mid + 1, high, key); } else { return mid; } }
迭代版:
// 迭代版本
public static int search(int[] data, int key) { if (data == null || data.length < 1) return -1; int low = 0; int high = data.length - 1; int mid; while (low <= high) { mid = (low + high) / 2; if (data[mid] > key) { high = mid - 1; } else if (data[mid] < key) { low = mid + 1; } else { return mid; } } return -1; }
JAVA 库中的二分查找使用非递归方式实现,返回结果与前面写的有所不同:找不到时返回的是负数,但不一定是-1
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}