一、实现
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (a[mid] == value) {
return mid;
} else if (a[mid] < value) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
二、注意事项
- 注意循环退出条件是 low<=high,而不是 low<high。
- 如果 low 和 high 比较大,两者之和就有可能溢出。改进方法是写成 low+((high-low)>>1)。
- low=mid+1,high=mid-1。注意这里的 +1 和 -1,如果直接写成 low=mid 或者 high=mid,可能会发生死循环。
三、变形
变体一:查找第一个值等于给定值的元素
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] >= value) {
high = mid - 1;
} else {
low = mid + 1;
}
}
if (low < n && a[low]==value) return low;
else return -1;
}
变体二:查找最后一个值等于给定值的元素
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else if (a[mid] < value) {
low = mid + 1;
} else {
if ((mid == n - 1) || (a[mid + 1] != value)) return mid;
else low = mid + 1;
}
}
return -1;
}
变体三:查找第一个大于等于给定值的元素
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] >= value) {
if ((mid == 0) || (a[mid - 1] < value)) return mid;
else high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
变体四:循环数组的二分查找
def cycleBsearch(lst, b):
if len(lst) == 0:
return -1
low = 0
high = len(lst) - 1
mid = (low + high) >> 1
while low <= high:
if lst[mid] == b:
return mid
if lst[low] <= lst[mid] <= lst[high]:
if b < lst[mid]:
high = mid - 1
else:
low = mid + 1
if lst[low] <= lst[mid] >= lst[high]:
if lst[low] <= b < lst[mid]:
high = mid - 1
else:
low = mid + 1
if lst[low] >= lst[mid] <= lst[high]:
if lst[mid] < b <= lst[high]:
low = mid + 1
else:
high = mid - 1
mid = (low + high) >> 1
return -1
变体五:查找最后一个小于等于给定值的元素
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else {
if ((mid == n - 1) || (a[mid + 1] > value)) return mid;
else low = mid + 1;
}
}
return -1;
}