二分查找:
二分查找适用有序数列
二分查找有两种一种递归,一种非递归
思路:
1首先确定该数组的中间的下标 mid=(left + right)/2
2然后让需要查找的数,findVal和arr[mid]比较
3。1如果:findVal > arr[mid] 说明你要查找的数在mid的右边,因此需要递归向右查找
3.2 如果findVal < arr[mid] 说明你要查找的数在mid的左边,因此需要递归向左查找
3.3 findVal = arr[mid] 找到了,返回
递归退出的条件:
1找到就结束递归
2遍历完整个数组,仍然没有找到findVal,也需要结束递归(当left>right)
实例代码
/**
*
* @MethodName: binarySearch
* @Description: TODO
* @author 63417
* @param arr 数组
* @param left 左边的索引
* @param right 右边的索引
* @param findVal 查找对象
* @return int 没有找到返回-1
* @date 2021年1月14日
*/
public static int binarySearch(int[] arr, int left, int right, int findVal) {
//当left>right 说明递归整个数组,但是没有找到
if(left > right) { //此处为一个没有查找到的出口
return -1;
}
int mid = (left + right) / 2;
int midVal = arr[mid];
if(findVal > midVal) { //向右递归
return binarySearch(arr, mid + 1, right, findVal);
} else if(findVal < midVal) { //向左递归
return binarySearch(arr, left, mid - 1, findVal);
} else {
return mid;
}
}
如果这个有序数组,需要查找的有多个相同的值,对代码优化如下:
//1、在找到mid值时,向mid索引值的左边扫描,将所有满足查找值的元素的下标,加入到一个集合中
//2、向mid的索引值的右边扫描,将所有满足查找值的元素下标加入集合
//3、返回集合
public static List<Integer> binarySearch1(int[] arr, int left, int right, int findVal) {
//当left>right 说明递归整个数组,但是没有找到
if(left > right) { //此处为一个没有查找到的出口
return new ArrayList<>(); //返回一个空的List,通过他的size就可以判断是否找到数据
}
int mid = (left + right) / 2;
int midVal = arr[mid];
if(findVal > midVal) { //向右递归
return binarySearch1(arr, mid + 1, right, findVal);
} else if(findVal < midVal) { //向左递归
return binarySearch1(arr, left, mid - 1, findVal);
} else {
List<Integer> resIndexlist = new ArrayList<>();
//向左边扫描
int temp = mid - 1;
while(true) {
if(temp < 0 || arr[temp] != findVal) {
break;
}
//否则就将temp加入集合
resIndexlist.add(temp);
temp -= 1;//temp左移
}
resIndexlist.add(mid);
//向mid索引的右边扫描
temp = mid + 1;
while(true) {
if(temp > arr.length - 1 || arr[temp] != findVal) {
break;
}
//否则就将temp加入集合
resIndexlist.add(temp);
temp += 1;//temp右移
}
return resIndexlist;
}
}