一、编写二分查找代码
前提:有已经排好序的数组A
定义左边界L,右边界R,确定搜索范围,循环执行二分查找(3、4两步)
获取中间索引M=(L+R)/2
中间索引的值A[M]与待搜索的值T进行比较
A[M]==T,表示找到,返回中间索引
A[M]>T,中间值右侧的其他元素都大于T,无需比较,到中间索引的左侧去找,M-1设置为右边界
A[M]<T,中间值左侧的其他元素都小于T,无需比较,到中间索引的右侧去找,M+1设置为左边界
当L>R时,表示没有找到,应结束循环
public class BinarySearch {
public static void main(String[] args) {
//排好序的数组
int[] array = {1, 5, 8, 11, 19, 22, 31, 40, 45, 48, 49, 50};
//目标值
int target = 48;
//返回的索引值
int idx = binarySearch(array, target);
System.out.println(idx);
}
//二分查找算法,找不到索引返回-1
public static int binarySearch(int[] a, int t) {
int left = 0; //初始化左边界
int right = a.length - 1;//初始化右边界
int mid;//定义中间索引值
while (left <= right) {
mid = (left + right) / 2;
if (a[mid] == t) {
return mid;
} else if (a[mid] > t){
right = mid - 1;
}else{
left = mid + 1;
}
}
return -1;
}
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/a30b6b3bd07ee9b9ab12c5f002beae86.png)
二、获取中间索引时,如何避免整数溢出?
什么是整数溢出?
整数溢出例子:左边界初始为0,右边界初始为int型最大值,第一次取mid时可以正常输出,第二次取mid时就会发生溢出,如下图
public class IntegerOverflow {
public static void main(String[] args) {
int left = 0;
int right = Integer.MAX_VALUE-1;
int mid=(left+right)/2;
System.out.println(mid);
}
}
第一次取mid
![](https://img-blog.csdnimg.cn/img_convert/dde1b605f8af48f4ffec18d9b3a513b2.png)
第二次取mid,发生溢出,正整数相加变成了负数
public class IntegerOverflow {
public static void main(String[] args) {
int left = 0;
int right = Integer.MAX_VALUE-1;
int mid=(left+right)/2;
System.out.println(mid);
//在右侧
left=mid+1;
mid=(left+right)/2;
System.out.println(mid);
}
}
![](https://img-blog.csdnimg.cn/img_convert/9fb967b2971c71ba0a5411ded0cb43a0.png)
如何解决整数溢出?
方法一:公式变换:left/2 +right/2 => left-left/2+right/2 =>left +(right-left)/2,这样可以保证right除以2不会发生溢出
public class IntegerOverflow {
public static void main(String[] args) {
int left = 0;
int right = Integer.MAX_VALUE-1;
int mid=left +(right-left)/2;//left/2 +right/2 => left-left/2+right/2 =>left +(right-left)/2
System.out.println(mid);
//在右侧
left=mid+1;
mid=left +(right-left)/2;
System.out.println(mid);
}
}
![](https://img-blog.csdnimg.cn/img_convert/1ae3813146d3313c1891540170860bac.png)
b. 方法二:右移一位的操作,这种方法不光能解决溢出问题,而且效率上要比除法高,因为CPU在处理移位运算所消耗的时钟周期比做除法小号的时钟周期短
![](https://img-blog.csdnimg.cn/img_convert/1eeb1a711c2d4bccc6fa5d82324a0005.png)
public class IntegerOverflow {
public static void main(String[] args) {
int left = 0;
int right = Integer.MAX_VALUE-1;
int mid=(right-left)>>>1;
System.out.println(mid);
//在右侧
left=mid+1;
mid=(right-left)>>>1;
System.out.println(mid);
}
}
结果没有溢出
![](https://img-blog.csdnimg.cn/img_convert/fafa4d2452e9d9e4543cde7cfda9ff17.png)