概述
二分查找(Binary Search)是一种在有序数组或列表中查找元素的快速有效的算法。二分查找通过反复将搜索区间划分为两半,并在其中之一中搜索目标元素,直到找到目标元素为止。
使用前提
-
有序数组:二分查找只适用于有序数组,即数组中的元素按照升序或降序排列。
-
随机访问能力:二分查找需要能够随机访问数组中的元素,即可以通过索引快速访问任意位置的元素。
-
元素比较可行:需要能够比较数组中的元素大小,确定目标元素与中间元素的大小关系,以确定查找范围的左右边界。
代码实现
//二分查找,找到返回对应索引,找不到返回-1
public int binarySearch(int [] ints , int target){
//先定义最大最小索引
int min = 0;
int max = ints.length - 1 ;
//循环条件为min和max之间还有元素(包括端点),此处必须加等号
while (min <= max){
int index = (min + max) / 2;//中间位置对应索引(向下取整)
int searchNum = ints[index];//中间位置对应值
if (target < searchNum){//说明taget在查找中间值左侧
max = index - 1;//让最大索引变为上一次比较的中间索引-1
} else if (searchNum < target) {//说明target在中间值的右边
min = index + 1;//让最大索引变为上一次比较的中间索引+1
} else {
return index;//说明查找值就是中间值
}
}
return -1;//当所有范围之间没有值的时候说明没找到;返回-1
}
问题:
java对数字的储存是保留符号位的,最高位为符号位,正数为0,负数为1,当两个特别大的正数相加进位到符号位,则会产生相加结果为负数的情况,那么在求中间索引的时候会得到index为负数的情况
int index = (min + max) / 2;//中间位置对应索引(向下取整)
改进方法:将求中间索引的算法改为
int index = (min + max) >>> 1 ;//中间位置对应索引(向下取整)
这样就可以保留最高位为0并且得到除以2向下取整的效果
应用:找到某元素第一次出现的位置
public int binarySearch(int [] ints , int target){
//先定义最大最小索引
int min = 0;
int max = ints.length - 1 ;
int result = -1;
//循环条件为min和max之间还有元素(包括端点),此处必须加等号
while (min <= max){
int index = (min + max) >>> 1;//中间位置对应索引(向下取整)
int searchNum = ints[index];//中间位置对应值
if (target < searchNum){//说明taget在查找中间值左侧
max = index - 1;//让最大索引变为上一次比较的中间索引-1
} else if (searchNum < target) {//说明target在中间值的右边
min = index + 1;//让最大索引变为上一次比较的中间索引+1
} else{
result = index;//说明找到了,索引留着候选
max = index - 1;//缩小范围在前一半
}
}
return result;//返回结果
}
找到最后一次出现的结果也是类似,只用将else中的内容改为
result = index;//说明找到了,索引留着候选
min = index + 1;//缩小范围在后一半