二分查找算法实现
二分查找算法是建立在排序好之后的数组,数组必须要先排好序,然后才能递归的使用二分查找算法。
原始二分查找思路分析
- 先取数组中间的数,当中间的数恰好是要查找的数,则直接返回即可
- 当中间的数大于要查找的数,说明目标数在左边,然后对左边进行递归查找
- 当中间的数小于要查找的数,则说明目标数在右边,需要对其进行递归查找
- 退出递归的条件是:当left的值大于right的值时,说明已经找完了
原始二分查找代码实现
package com.njupt.search;
/**
* Creat with IntelliJ IDEA
*
* @Auther:倔强的加瓦
* @Date:2021/07/21/12:14
* @Description:
*/
public class Erfen {
public static void main(String[] args) {
int[] arr = {3, 4, 5, 6, 7, 8, 9, 12, 13, 34, 56};
int result = erfenSearch(arr, 0, arr.length - 1, 4);
if (result != -1) {
System.out.println("目标数下标为:" + result);
} else {
System.out.println("没有此目标数");
}
}
public static int erfenSearch(int[] arr, int left, int right, int target) {
if (left > right) {
return -1;
}
int middle = (left + right) / 2;
//说明在中间数的右边
if (target > arr[middle]) {
return erfenSearch(arr, middle + 1, right, target);
// 否则在target的左边
} else if (target < arr[middle]) {
return erfenSearch(arr, left, middle - 1, target);
} else {
return middle;
}
}
}
测试结果:
目标数下标为:1
存在的问题是:如果数组中要查找的元素不止一个,则原始方法不能实现,故对此原始方法进行了完善
改善的二分查找法
基本思路:
- 在原始二分查找法的基础之上,先找到目标
- 找到目标之后,由于是排好序的,其他的相同值肯定在目标值的周围,所以只需要进行目标元素周围的搜索就可以了。
package com.njupt.search;
import java.util.ArrayList;
import java.util.List;
/**
* Creat with IntelliJ IDEA
*
* @Auther:倔强的加瓦
* @Date:2021/07/21/14:31
* @Description:解决二分查找中不能重复查找相同元素的问题
*/
public class BetterErfen {
public static void main(String[] args) {
int[] arr = {1, 4, 6, 8, 9, 17, 17, 17, 17, 17, 17, 23, 34};
List<Integer> result = betterBinarySort(arr, 0, arr.length - 1, 17);
System.out.println("结果:" + result);
}
public static List<Integer> betterBinarySort(int[] arr, int left, int right, int target) {
if (left > right) {
//如果没有则返回空的
return new ArrayList<>();
}
int middle = (left + right) / 2;
if (target > arr[middle]) {
return betterBinarySort(arr, middle + 1, right, target);
} else if (target < arr[middle]) {
return betterBinarySort(arr, left, middle - 1, target);
}//走到此处,说明找到第一个
else {
List<Integer> list = new ArrayList();
//由于都是排好序的,则当找到一个值之后,和其相同的值都在他的周围,
//故只需要在其周围进行一步一步的搜索即可。
//先把自身也加进去
list.add(middle);
int tempRight = middle;
//先对其右边搜索
while (true) {
tempRight = tempRight + 1;
if (tempRight > right || arr[tempRight] != arr[middle]) {
break;
} else {
list.add(tempRight);
}
}
int tempLeft = middle;
//对其左边扫描
while (true) {
tempLeft = tempLeft - 1;
if (tempLeft < 0 || arr[tempLeft] != arr[middle]) {
break;
}
list.add(tempLeft);
}
return list;
}
}
}
结果:就是数组中下标为这些的数据为要查的元素。
结果:[6, 7, 8, 9, 10, 5]