Java 实现的各种二分查找方法解析
在算法与数据结构中,二分查找是一种常用且高效的搜索技术。本文详细解析 Java 实现的几种二分查找方法,涵盖不同场景下的应用:
- 查找相同 key 的最小下标和最大下标。
- 查找小于 key 的最大下标。
- 查找大于 key 的最小下标。
核心思路
二分查找的基本思想是:
- 将搜索范围从中间分为两半,依次缩小范围。
- 根据条件调整左指针
l
或右指针r
。 - 循环结束时确定结果。
下面代码展示了不同场景下的二分查找方法。
完整代码
/**
* 各种二分查找方法实现
* 包括:
* 1. 查找相同 key 的最小和最大下标。
* 2. 查找小于 key 的最大下标。
* 3. 查找大于 key 的最小下标。
* 适用于升序排序的数组。
*/
public class BinSearch {
/**
* 查找相同 key 的最小下标
* 思路:向左不断收缩范围,最后的位置即为结果
*/
public static int low_search(int[] arr, int key) {
int l = 0;
int r = arr.length - 1;
while (l <= r) {
int mid = (l + r) >> 1;
if (arr[mid] >= key) {
r = mid - 1;
} else {
l = mid + 1;
}
}
if (l < arr.length && arr[l] == key) {
return l;
}
return -1;
}
/**
* 查找相同 key 的最大下标
* 思路:向右不断收缩范围,最后的位置即为结果
*/
public static int high_search(int[] arr, int key) {
int l = 0;
int r = arr.length - 1;
while (l <= r) {
int mid = (l + r) >> 1;
if (arr[mid] > key) {
r = mid - 1;
} else {
l = mid + 1;
}
}
if (r >= 0 && arr[r] == key) {
return r;
}
return -1;
}
/**
* 查找小于 key 的最大下标
* 思路:当值大于等于 key 时向左收缩,否则向右收缩。
*/
public static int small_search(int[] arr, int key) {
int l = 0;
int r = arr.length - 1;
while (l <= r) {
int mid = (l + r) >> 1;
if (arr[mid] >= key) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return r; // r 越界时为 -1,直接返回
}
/**
* 查找大于 key 的最小下标
* 思路:当值小于等于 key 时向右收缩,否则向左收缩。
*/
public static int big_search(int[] arr, int key) {
int l = 0;
int r = arr.length - 1;
while (l <= r) {
int mid = (l + r) >> 1;
if (arr[mid] > key) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return l >= arr.length ? -1 : l; // 如果越界,返回 -1
}
}
详细解析
方法一:查找相同 key 的最小下标
核心逻辑
- 目标:找到第一个等于 key 的元素。
- 每次检查
arr[mid]
是否大于等于key
,如果是,则向左收缩范围,否则向右收缩。
示例
输入数组:[1, 2, 2, 2, 3]
,key = 2
- 输出结果:
1
(第一个 2 的下标)
方法二:查找相同 key 的最大下标
核心逻辑
- 目标:找到最后一个等于 key 的元素。
- 每次检查
arr[mid]
是否小于等于key
,如果是,则向右收缩范围,否则向左收缩。
示例
输入数组:[1, 2, 2, 2, 3]
,key = 2
- 输出结果:
3
(最后一个 2 的下标)
方法三:查找小于 key 的最大下标
核心逻辑
- 目标:找到所有小于 key 的元素中最大的下标。
- 每次检查
arr[mid]
是否大于等于key
,如果是,则向左收缩范围,否则向右收缩。
示例
输入数组:[1, 2, 3, 4, 5]
,key = 4
- 输出结果:
2
(下标对应值为 3)
方法四:查找大于 key 的最小下标
核心逻辑
- 目标:找到所有大于 key 的元素中最小的下标。
- 每次检查
arr[mid]
是否小于等于key
,如果是,则向右收缩范围,否则向左收缩。
示例
输入数组:[1, 2, 3, 4, 5]
,key = 3
- 输出结果:
3
(下标对应值为 4)
总结
- 二分查找的灵活性:通过调整条件,二分查找可以适配多种场景。
- 边界处理:实现时需注意数组越界情况,例如返回值为
-1
表示查找失败。 - 性能优势:二分查找时间复杂度为
O(log n)
,适用于大规模数据的搜索。
通过以上实现,您可以轻松解决数组中的多种查找需求。