折半查找的实现(Java)与讲解-常见数据结构
1、讲解
也称二分搜索,对数搜索,是用来在一个有序数组中查找某一元素的算法。
例子:在一个升序数组中查找一个数。每次考察数组当前部分的中间元素(middle),如果中间元素刚好是目标元素(target),就结束搜索。如果中间元素小于所查找的值,就在数组左半部分[left,middle]查找;如果中间元素大于所查找的值,就在数组右半部分[middle,right]查找。
二分搜索法可以用来查找满足某一条件的最大(最小)值。
要求满足某种条件的最大值最小可能情况(最大值最小化),首先的想法是从小到大枚举这个作为答案的[最大值],然后去判断是否合法。若答案单调,就可以使用二分搜索法来更快的找到答案
使用二分搜索法解决[最大值最小化]条件:
- 答案在一个固定区间内
- 比较容易判断某个值是否符合条件
- 可行解对于区间满足一定的单调性(x符合条件,那么x-1或x+1也符合条件)
- 时间复杂度:最优情况O(1),平均/最坏时间复杂度O(log n)
2、实现
算法思路
假设目标值在闭区间[l,r]
中,每次将区间长度缩小一半,当l=mid
时,找到目标值
区间[l,r]
划分为[l,mid-1]
和[mid+1,r]
;更新操作为r=mid-1
或l=mid+1。
package top.alibra.algorithm;
public class Dichotomy {
//折半查找(二分法查找):前提数组有序
public static int dichotomySearch(int[] nums, int target) {
if(nums == null || nums.length == 0){ //判断数组为空
return -1;
}
int l = 0, r = nums.length - 1; //设置左右边界
while(l <= r){
int mid = l + (r-l) / 2; // 等同于mid=(l+r)/2,这种写法是为了防止数组越界,也可以写为(l+r) >>> 1
if(nums[mid] == target){ //最终target=mid,返回mid
return mid;
}else if(nums[mid] < target) { //目标值在(mid,r]之间
l = mid + 1;
}else { //目标值在[l,mid)之间
r = mid - 1;
}
}
// 最后判断: l>r 即数组不存在
return -1;
}
//测试
public static void main(String[] args) {
//定义一个属数组
int[] arr={1,3,9,11,12,13,17,24,51,86,87,92,99};
int num = dichotomySearch(arr,17);
System.out.println(num);
}
}