1.初次相识
二分查找又称折半查找,是一种在有序数组中查找特定元素的算法。二分查找的基本思想是:通过不断地二分数组的中间元素,缩小查找区间,直到找到目标元素或者确定目标元素不存在为止。
二分查找的时间复杂度为O(logn),比线性查找的时间复杂度O(n)要小很多,但是二分查找的前提是必须在有序数组中进行。
2.思想分析
- 1.确定该数组的中间下标 middle=(left+right)/2
- 2.需要查找的数index和array【middle】比较
- 2.1 index > array【middle】,说明要查找的数在middle的右边,递归向右查找
- 2.2 index < array【middle】,说明要查找的数在 middle的左边,递归向左查找
- 2.3 index == array【middle】,说明找到,返回
- 什么时候递归结束??
- 1.找到就结束
- 2.递归完整个数组,未找到,也许结束,条件: lift > rigtht
3.代码实现
public static int binarySearch(int[] arr, int left, int right, int index) {
//直接结束递归
if (left > right) {
return -1;
}
int middle = (left + right) / 2;
int middleVal = arr[middle];
if (index > middleVal) {
return binarySearch(arr, middle + 1, right, index);
} else if (index < middleVal) {
return binarySearch(arr, left, middle - 1, index);
} else {
return middle;
}
}
发现一个问题,如果有重复数字,也只能返回第一数字的下标
4.代码优化
思路:
- 1.再找到middle时,不要立马返回
- 2.向middle索引的左边扫描,将满足条件元素的下标,加入到ArrayList集合
- 3.向middle索引的右边扫描,将满足条件元素的下标,加入到ArrayList集合
- 4.将ArrayList返回
public static ArrayList<Integer> binarySearch(int[] arr, int left, int right, int index) {
//直接结束递归
if (left > right) {
return new ArrayList<Integer>();
}
int middle = (left + right) / 2;
int middleVal = arr[middle];
if (index > middleVal) {
return binarySearch(arr, middle + 1, right, index);
} else if (index < middleVal) {
return binarySearch(arr, left, middle - 1, index);
} else {
ArrayList<Integer> list = new ArrayList<>();
int temp = middle - 1;//向左边查找的第一个元素
while (true) {
if (temp < 0 || arr[temp] != middleVal) {//退出条件
break;
}
list.add(temp);//找到,放进集合
temp--;//temp左移
}
list.add(middle);//中间的放进去
temp = middle + 1;
while (true) {
if (temp > arr.length - 1 || arr[temp] != middleVal) {
break;
}
list.add(temp);
temp++;
}
return list;
}
}
5.测试一把
public static void main(String[] args) {
int[] array = new int[]{1, 2, 3, 4, 5, 6, 6};
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要查找的数字:");
int num = scanner.nextInt();
ArrayList<Integer> lists = binarySearch(array, 0, array.length - 1, num);
System.out.println("你查找的数字:" + num + ",下标:" + lists);
}