Java实现二分法的案例,什么是二分法
二分法
概念:
- 二分法(Bisection method) 即一分为二的方法,又叫折半查找方法。
- 把一组有序数列分为左右两部分,从这组数字的中间位置开始找:
- 如果中间位置的数等于目标数,则直接返回;
- 如果中间位置的数大于目标数,则从左边部分查找;
- 如果小于目标数,则从右边部分查找;
- 重复以上过程,直到找到满足条件的记录,使查找成功。
时间复杂度:
都是 O(log2 N)
空间复杂度:
非递归方式: 空间复杂度是O(1);
递归方式: 空间复杂度:O(log2N )
实现
1. 递归方式
public static int binarySearchRecursive(int[] arr, int low, int high, int key) {
//边界条件:如果目标数没有在数组范围内(即比最左边的数小,比最右边的数大)
if (arr == null || arr.length == 0 || arr[low] > key || arr[high] < key || low > high) {
return -1;
}
// 获取中间位置下标
int mid = (low + high) / 2;
// 将中间位置的数和目标数作比较,如果中间位置的数等于目标数,则直接返回下标,
// 如果中间位置的数大于目标数,则将左边部分用递归方法继续查找;如果小于目标数,则从右边部分用递归方法继续查找
if (arr[mid] == key) {
return mid;
} else if (arr[mid] > key) {
return binarySearch(arr, low, mid - 1, key);
} else {
return binarySearch(arr, mid + 1, high, key);
}
}
// 测试下:从一组数中找3,输出数组下标
public static void main(String[] args) {
int[] arr = {2, 3, 5, 7, 9, 78, 90, 167};
System.out.println(binarySearchRecursive(arr, 0, (arr.length) - 1, 3));
}
2. 非递归方式
public static int binarySearch(int[] arr, int key) {
int low = 0;
int high = arr.length - 1;
while (low <= high) {
int middle = (low + high) / 2;
if (key < arr[middle]) {
high = middle - 1;
} else if (key > arr[middle]) {
low = middle + 1;
} else {
return middle;
}
}
return -1;
}
// 测试下:从一组数中找3,输出数组下标
public static void main(String[] args) {
int[] arr = {2, 3, 5, 7, 9, 78, 90, 167};
System.out.println("数组下标:"+binarySearch(arr, 3));
}
3.非递归
/**
* 二分查找
* @param srcArray 源数组
* @param des 目标元素
* @return 如果找到则返回索引位置,找不到则返回-1
*/
public static int binarySearch(int[] srcArray, int des) {
//定义初始最小、最大索引
int start = 0;
int end = srcArray.length - 1;
//确保不会出现重复查找,越界
while (start <= end) {
//计算出中间索引值 >>> 逻辑右移 也就是 int middle = (end + start)/2
int middle = (end + start)>>>1 ;//防止溢出
if (des == srcArray[middle]) {
return middle;
//判断下限
} else if (des < srcArray[middle]) {
end = middle - 1;
//判断上限
} else {
start = middle + 1;
}
}
//若没有,则返回-1
return -1;
}