由于前面的算法while循环内都是采用if-else来做判断,所以会导致一个问题:如果查找值没有刚好处在中间值的位置,那么它每循环一次,都要判断两次。
现在我们修改一下:循环内只做范围筛选,最后剩下一个数,另外再去判断它是不是我们要的数
//二分查找法减少判断次数
public void testApp5() {
//查找范围
int[] arr = new int[100000000];
for (int i = 1; i <= 99999999; i++) {
arr[i-1] = i;
}
//查找目标
int target = 59469999;
//初始化左右边界
int i=0,j=arr.length;//还是采用右开
long Start=System.nanoTime();//开始时间
//初始化中间值
while (1<j-i){//当j-i=1时,中间值为i,即为最后一个元素,此时不用再判断,直接输出
//设中间值索引
int m=(i+j)>>>1;
if(target<arr[m]){
j=m;//目标小于中间数,排除右边范围,由于前面j取的是超出索引的开区间,所以这里不用-1
}else{
i=m;//目标大于中间数,排除左边查找范围
}
}
//最后只剩一个元素判断一下是否命中查找目标值
if(target==arr[i]){
long End=System.nanoTime();//结束时间
System.out.println("找着了,索引为:"+i);//命中则输出索引,程序结束
System.out.println("耗时:"+(End-Start)/Math.pow(10,6)+"ms");//耗时
}else{
//未命中则输出-1
System.out.println("未找到,-1");
long End=System.nanoTime();//结束时间
System.out.println("耗时:"+(End-Start)/Math.pow(10,6)+"ms");//耗时
}
}
这样每循环一次就减少一次判断,大体上减少了时间复杂度