我们先给出我们最常见的用来在排序序列找到特定数字的Binary Search的做法。
public static int BinarySearch(int[] arr, int t) {
int head = 0;
int tail = arr.length;
while (head <= tail) {
int mid = (head + tail) / 2;
if (arr[mid] < t) {
head = mid + 1;
} else if (arr[mid] > t){
tail = mid - 1;
} else {
return mid;
}
}
return -1;
}
可以看到的是这个只能返回特定的数字的位置。找不到返回-1。
接下来就给另外两种变形:
public static int MajorBinarySearch(int[] arr, int t) {
int head = 0;
int tail = arr.length;
while (head <= tail) {
int mid = (head + tail) / 2;
if (arr[mid] < t) {
head = mid + 1;
} else {
tail = mid - 1;
}
}
return head;
}
public static int MinorBinarySearch(int[] arr, int t) {
int head = 0;
int tail = arr.length;
while (head <= tail) {
int mid = (head + tail) / 2;
if (arr[mid] > t) {
tail = mid - 1;
} else {
head = mid + 1;
}
}
return tail;
}
首先要说明的是,上面两种BinarySearch都具备最基本的BinarySearch的功能,就是能够返回给定数字(如果存在)的位置。但是根据算法得知,即使是找到了,我们还是会不停取中直到临界状态。所以如果只是为了找特定数字,performance是要稍差的。
但是这两者还具备另一个功能,如果数字不存在,MajorBinarySearch会返回刚好比它大的数字的第一个位置(允许存在重复),这个适合的一个例子是找数字的插入位置。
MinorBinarySearch会返回刚好比它小的数字的最后一个位置。
也就是{1,3,5,5,7,7,7,7,7,9}这个数组里如果找6,MajorBinarySearch会返回4,MinorBinarySearch会返回3。当然如果这个数组里有6,也是会准确返回其位置的。(但是细节不能搞混,否则就会失去返回要找的数字的位置的功能,因为一个返回tail另一个返回head。这是一个比较tricky的地方。)
一般前者用途会多一些,后者也会有特殊的用途。譬如Insert Interval这一题就是一个MinorBinarySearch的用例。