- 前提条件
- 二分查找流程
- 定义左边界L,右边界R,确定当前的搜索范围,循环进行二分查找
- 获取当前搜索范围的中间索引mid = (L + R) / 2
- 将数组arr[mid]与目标值target进行比较
- 如果arr[mid] > target,说明当前目标值在中间索引的左侧,将右边界R = mid - 1,重新确定当前查找范围
- 如果arr[mid] < target,说明当前目标值在中间索引的右侧,将左边界L = mid + 1,重新确定当前查找范围
- 如果arr[mid] = target,返回当前中间索引mid
- 当L > R时,表示当前数组中没有找到目标值,应返回-1
- 代码演示
public static void main(String[] args) {
int[] arr = new int[]{2, 5, 7, 8, 9, 22, 35, 46, 65, 76, 79, 83, 87, 88, 99, 567};
int target = 35;
int index = binarySearch(arr, target);
System.out.println(index);
}
public static int binarySearch(int[] arr, int target) {
int l = 0;
int r = arr.length - 1;
int mid;
while (l <= r) {
mid = (l + r) / 2;
if (arr[mid] > target) {
r = mid - 1;
}
else if (arr[mid] < target) {
l = mid + 1;
}
else {
return mid;
}
}
return -1;
}
- 整数溢出问题
- 在上述代码中,计算中间索引时mid = (L + R) / 2,可能会导致整数溢出问题,计算的mid值为负数
- 当数组的长度过大时,对于R = Integer.MAX_VALUE时,并且目标值target在中间索引mid的右侧,在下一次计算中mid值会出现负数
- 解决整数溢出问题
- 将mid = (L + R) / 2替换为 L + (R - L) / 2
- 将mid = (L + R) / 2替换为(L + R) >>> 1
- 第二种方式对比与第一种方式效率会高一些,但只针对正数进行操作,将当前数值向右移动一位