一、實現
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;
}