思路分析
- 首先确定该数组的中间的下标
mid = (left + right) / 2 - 然后让需要查找的数 findVal 和 arr[mid] 比较
2.1 findVal > arr[mid] , 说明你要查找的数在mid 的右边, 因此需要递归的向右查找
2.2 findVal < arr[mid], 说明你要查找的数在mid 的左边, 因此需要递归的向左查找
2.3 findVal == arr[mid] 说明找到,就返回
什么时候我们需要结束递归.
- 找到就结束递归
- 递归完整个数组,仍然没有找到findVal ,也需要结束递归 当 left > right 就需要退出
代码实现(1)
普通的二分查找的实现(即数组中值都是有序的,并且没有重复的值)
/**
* title:二分查找
* date :2020.3.4
*/
package search;
//注意:使用二分查找的数组必须是有序的
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1,8,11,15,18,26,99};
int resIndex = binarySearch(arr,0,arr.length - 1,999);
System.out.printf("resIndex=%d\n",resIndex);
}
//二分查找算法
/**
*
* @param arr 数组
* @param left 左边的索引
* @param right 右边的索引
* @param findVal 要查找的值
* @return 如果找到就返回下标,如果没有,就返回-1;
*/
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,8, 10, 89, 1000, 1000,1234} 当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到,比如这里的 1000.
/**
* title:二分查找
* date :2020.3.4
*/
package search;
import java.util.ArrayList;
import java.util.List;
//注意:使用二分查找的数组必须是有序的
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1,8,11,15,18,18,18,18,18,18,26,99,10245};
//int resIndex = binarySearch(arr,0,arr.length - 1,999);
//System.out.printf("resIndex=%d\n",resIndex);
List<Integer> resIndexList = binarySearch2(arr,0,arr.length - 1,18);
System.out.println("resIndex="+resIndexList);
}
//二分查找算法
/**
*
* @param arr 数组
* @param left 左边的索引
* @param right 右边的索引
* @param findVal 要查找的值
* @return 如果找到就返回下标,如果没有,就返回-1;
*/
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,8, 10, 89, 1000, 1000,1234} 当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到,比如这里的 1000.
/**
* 思路分析
* 1.在找到mid索引值时,不要马上返回
* 2.向mid的左边扫描,将所有满足1000的元素的下标,加入到Arrylist
* 3.想mid的右边扫描,将所有满足1000的下标加入到Arryllist
* 4.将Arrylist返回
*/
public static ArrayList<Integer> binarySearch2(int[] arr,int left,int right,int findVal) {
//当left > right ,说明帝国了整个数组,但是没有找到
if(left > right ) {
return new ArrayList<Integer>();
}
int mid = (left + right) /2;
int midVal = arr[mid];
if(findVal > midVal) {//向右递归
return binarySearch2(arr,mid+1,right,findVal);
}else if(findVal <midVal) {//向左递归
return binarySearch2(arr,left,mid -1 ,findVal);
}
else {
// * 1.在找到mid索引值时,不要马上返回
// * 2.向mid的左边扫描,将所有满足1000的元素的下标,加入到Arrylist
// * 3.想mid的右边扫描,将所有满足1000的下标加入到Arryllist
// * 4.将Arrylist返回
ArrayList<Integer> resIndexList = new ArrayList<Integer>();
int temp = mid -1;
while(true) {
if(temp <0 || arr[temp] != findVal) {
break;
}
//否则就把temp放入集合中
resIndexList.add(temp);
temp -= 1;//temp左移动
}
resIndexList.add(mid);
//.想mid的右边扫描,将所有满足1000的下标加入到Arryllist
temp = mid +1;
while(true) {
if(temp >arr.length-1 || arr[temp] != findVal) {
break;
}
//否则就把temp放入集合中
resIndexList.add(temp);
temp += 1;//temp左移动
}
return resIndexList;
}
}
}