二分查找的前提是数组为有序数组
二分查找是一种效率极高的算法,时间复杂度在O(logn)量级。其应用非常广,例如快速定位IP属地,MySQL InnoDB 引擎的底层实现等。
第一种
我们定义 target 是在一个在左闭右闭的区间里,也就是[left, right] (这个很重要非常重要) 。
区间的定义这就决定了二分法的代码应该如何写,因为定义target在[left, right]区间,所以有如下两点:
- while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
- if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
/**
* 创建时间: 2022/9/13
* 函数名称: binarySearch
* 函数功能: 二分查找
* 函数参数:
* @param arr: 数组
* @param target: 查找的目标值
* @return: int: 返回目标值在数组中的位置(-1表示没有查找到)
* @author: Snow
*******************************************************
*/
int binarySearch(int[] arr, int target){
if(target > arr[arr.length - 1] || target < arr[0]){
return -1;
}
int mid;
int left = 0;
int right = arr.length - 1;
while (left <= right){
mid = left + (right - left) / 2;
if(target > arr[mid]){
left = mid + 1;
}else if(target < arr[mid]){
right = mid - 1;
}else {
return mid;
}
}
return -1;
}
第二种
第一种方法会了,第二种就很容易出来了。递归其实就是第一种的变种。
/**
* 创建时间: 2022/9/13
* 函数名称: binarySearchRecursion
* 函数功能: 二分查找(递归方式)
* 函数参数:
* @param arr: 数组
* @param target: 查找的目标值
* @return: int: 返回目标值在数组中的位置(-1表示没有查找到)
* @author: Snow
*******************************************************
*/
int binarySearchRecursion(int[] arr, int left, int right, int target){
if(target > arr[right] || target < arr[left]){
return -1;
}
int mid = left + (right - left) / 2;
if(target > arr[mid]){
return binarySearchRecursion(arr, mid + 1, right, target);
}else if(target < arr[mid]){
return binarySearchRecursion(arr, left, mid - 1, target);
}else {
return mid;
}
}
~~END~~