简介
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
顾名思义,二分查找就是从中间开始查找,如果中间的值比目标值大,则结果要么在左边,要么不存在,反之则结果要么在右边,要么不存在,以此类推进行下一步查找……
二分查找的运行时间为对数时间:
$$
O(log_2n)
$$
假设从 [0,99] 中查找目标位置最多只需要查找 7 次(2^6 < 100 < 2^7)
递归实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class BinarySearch {
public int binarySearch(int[] arr, int target) { return binarySearch(arr, 0, arr.length - 1, target); }
public int binarySearch(int[] arr, int left, int right, int value) { if (arr[0] > value || arr[arr.length - 1] < value || right - left < 0) { return -1; } int mid = (left + right) / 2;
if (arr[mid] == value) { return mid; } else if (arr[mid] > value) { return binarySearch(arr, left, mid - 1, value); } else { return binarySearch(arr, mid + 1, right, value); } } }
|
非递归实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class BinarySearch2 {
public int binarySearch(int[] arr, int target) {
int left = 0; int right = arr.length - 1;
while (left <= right) { int mid = (left + right) / 2; if (arr[mid] == target) { return mid; } else if (arr[mid] > target) { right = mid - 1; } else { left = mid + 1; } } return -1; } }
|
mid 的计算:
mid = (left + right) / 2
mid = left + (right - left) / 2
l + h 可能出现加法溢出,也就是说加法的结果大于整型能够表示的范围。但是 l 和 h 都为正数,因此 h - l 不会出现加法溢出问题。所以,最好使用第二种计算法方法。