开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第二十二天,点击查看活动详情
前言:上一文大家了解到了查找算法,接下来给大家详细解说二分查找算法~
二分查找 / 折半查找
- 必须是顺序的数组,若是无序的,则需要先排序(小到大 / 大到小)
思路
(以下是排序已为由小到大)
-
首先确定该数组的中间下标
- mid = (left + right)/ 2
-
然后让需要查找的数 findValue 和 arr[mid] 进行比较
- findValue > mid[arr] :说明要查找的数在 mid 的右边,应该向右查找(向右递归查找)
- findValue < mid[arr] :说明要查找的数在 mid 的左边,应该向左查找(向左递归查找)
- findValue = mid[arr] :说明已经找到,则返回
-
退出递归
- 找到目标退出递归
- 找不到退出递归 (==left > right==)
/**
* @author Kcs 2022/9/5
*/
public class BinarySearch {
public static void main(String[] args) {
//有序数组
int[] arr = {0, 11, 22, 33, 44, 45, 55, 77, 88, 88, 88, 88, 99};
// int index = binarySearch(arr, 0, arr.length - 1, 12);
// System.out.println("index=" + index);
List<Integer> integers = binarySearch2(arr, 0, arr.length - 1, 99);
System.out.println(integers);
}
/**
* 二分查找算法
* @param arr 查找数组
* @param left 左边索引
* @param right 右边索引
* @param findValue 查找的值
* @return index
*/
public static int binarySearch(int[] arr, int left, int right, int findValue) {
//没有找到
if (left > right) {
return -1;
}
//中间索引
int mid = (left + right) / 2;
//中间值
int midValue = arr[mid];
//判断递归的方向
//向右
if (findValue > midValue) {
return binarySearch(arr, mid + 1, right, findValue);
} else if (findValue < midValue) {
return binarySearch(arr, left, mid - 1, findValue);
} else {
//查找到所有相同的值,并返回
return mid;
}
}
/**
* 查找重复的值索引
* @param arr
* @param left
* @param right
* @param findValue
* @return
*/
public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int findValue) {
//没有找到
if (left > right) {
return new ArrayList<Integer>();
}
//中间索引
int mid = (left + right) / 2;
//中间值
int midValue = arr[mid];
//判断递归的方向
//向右
if (findValue > midValue) {
return binarySearch2(arr, mid + 1, right, findValue);
} else if (findValue < midValue) {
return binarySearch2(arr, left, mid - 1, findValue);
} else {
ArrayList<Integer> resIndexlist = new ArrayList<>();
int temp = mid - 1;
//向mid左边开始继续搜索
while (true) {
//退出
if (temp < 0 || arr[temp] != findValue) {
break;
}
resIndexlist.add(temp);
temp -= 1;
}
resIndexlist.add(mid);
//向mid右边继续搜索
temp = mid + 1;
while (true) {
if (temp > (arr.length - 1) || arr[temp] != findValue) {
break;
}
resIndexlist.add(temp);
temp += 1;
}
return resIndexlist;
}
}
}