简介
分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且元素必须是有序的。
思路
前提:数组中的元素顺序排序:
- 先确定数组的中间数的下标 mid = (left + right) / 2;
- 让查找的数value与中间数arr[mid]比较
1. value > arr[mid],说明value在mid的右边,需要向右递归
2. value < arr[mid],说明value在mid的左边,需要向左递归
3. value = arr[mid],说明找到了,返回下标
什么时候结束递归: - 找到了结束递归
- 递归完整个数组都没有找到,结束递归,即:left > right
代码
/**
* @param arr 数组
* @param left 数组左边的索引
* @param right 数组右边的索引
* @param value 要查找的数字
* @return 找到值的下标,没找到就返回空集合
*/
public static int binarySearch (int[] arr,int left,int right,int value) {
//找了一遍都没有找到
if (left > right || value < arr[0] || value > arr[arr.length - 1]) {
return -1;
}
int mid = (left + right) / 2;
int midValue = arr[mid];
if (value > midValue) {
return binarySearch(arr,mid + 1,right,value);
} else if (value < midValue) {
return binarySearch(arr,left,mid - 1,value);
} else {
return mid;
}
}
测试
int[] arr = {1,2,3,4,5,6,6,6};
int result = binarySearch(arr,0,arr.length - 1,6);
System.out.println("result = " + result);
如果需要查找多个值,可以对代码进行改进,找到值时,先把下标添加到集合中去,然后分别向左递归、向右递归,把下标添加到集合中去,最后返回集合
public static List<Integer> binarySearch2 (int[] arr, int left, int right, int value) {
if (left > right || value < arr[0] || value > arr[arr.length - 1]) {
return new ArrayList<>();
}
int mid = (left + right) / 2;
int midValue = arr[mid];
if (value > midValue) {
return binarySearch2(arr,mid + 1,right,value);
} else if (value < midValue) {
return binarySearch2(arr,left,mid - 1,value);
} else {
List<Integer> list = new ArrayList<>();
list.add(mid);
int temp = mid - 1;
//向左递归
while (temp >= 0 && arr[temp] == value) {
list.add(temp);
temp -= 1;
}
temp = mid + 1;
//向右递归
while (temp <= arr.length - 1 && arr[temp] == value) {
list.add(temp);
temp += 1;
}
return list;
}
}
测试
int[] arr = {1,2,3,4,5,6,6,6};
List<Integer> list = binarySearch2(arr,0,arr.length - 1,6);
if (!list.isEmpty()) {
System.out.println("list = " + Arrays.toString(list.toArray()));
} else {
System.out.println("没有找到");
}