1、二分查找
请对一个有序数组进行二分查找 {1,8, 10, 89, 1000, 1234} ,输入一个数看看该数组是否存在此数,并且求出下标,如果没有就提示"没有这个数"。
2、二分查找思路
-
首先确定该数组的中间的下标mid = (left + right) / 2;
-
然后让需要查找的数 findVal 和 arr[mid] 比较
(1)findVal > arr[mid] ,说明你要查找的数在mid 的右边, 因此需要递归的向右查找;
(2)findVal < arr[mid], 说明你要查找的数在mid 的左边, 因此需要递归的向左查找;
(3) findVal == arr[mid] 说明找到,就返回。
3.什么时候我们需要结束递归
(1)找到就结束递归
(2)递归完整个数组,仍然没有找到findVal ,也需要结束递归 当 left > right 就需要退出。
(a)递归代码
/**
* 【默认数组是升序的】
* @param arr:数组
* @param left:左侧索引
* @param right:右侧索引
* @param value:查找的值
* @return:如果找到就返回下标,如果没有找到就返回下标
*/
public static int binarySearch(int[] arr, int left, int right, int findValue) {
//当left>right时,说明递归完毕
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;
}
}
测试代码
int[] arr = { 1, 8, 10, 89,89,89,1000, 1234 };
int resIndex=binarySearch(arr,0,arr.length-1,89);
if(resIndex == -1){
System.out.println("没有这个数......");
}else{
System.out.println("找到了,下标是"+resIndex);
}
(b)非递归
//二分查找,非递归
public static int binarySearch01(int[] arr,int left,int right,int findValue){
int i = left;
int j = right;
while (i <= j) {
int mid = (i + j) / 2; //得到中间下标
if(findValue>arr[mid]){
//向右找,换左下标
i = mid+1;
}else if(findValue<arr[mid]){
//向左找,换右下标
j = mid-1;
}else{
return mid;
}
}
return -1;
}
3、思考
{1,8, 10, 89, 1000, 1000,1234} 当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到,比如这里的 1000。
思路分析
(1)在找到mid索引值时,不要马上返回;
(2)向mid索引值左边扫描,将所有满足1000的元素的下标,加入到集合ArrayList中;
(3)向mid索引值右边扫面,将所有满足1000的元素的下标,极速到集合ArrayList中;
(4)将ArrayList返回就行。
代码实现
public static List<Integer>binarySearch02(int[] arr,int left,int right,int findValue){
if (left > right) {
return new ArrayList<Integer>(); //返回空的ArrayList
}
int mid = (left + right) / 2;
int midValue = arr[mid];
if (findValue > midValue) {
// 向右递归
return binarySearch02(arr, mid + 1, right, findValue);
} else if (findValue < midValue) {
// 向左递归
return binarySearch02(arr, left, mid - 1, findValue);
} else {
/*
* 1、在找到mid索引值时,不要马上返回
* 2、向mid索引值左边扫描,将所有满足1000的元素的下标,加入到集合ArrayList中
* 3、向mid索引值右边扫面,将所有满足1000的元素的下标,极速到集合ArrayList中
* 4、将ArrayList返回就行
*/
// 创建ArrayList
List<Integer> resIndexList = new ArrayList<Integer>();
// 向左边扫描
int temp = mid - 1;
while (true) {
if (temp < 0 || arr[temp] != findValue) {
//退出
break;
}
//否则就把temp放到resIndexList
resIndexList.add(temp);
temp--; //temp左移
}
resIndexList.add(mid); //将中间这个放进resIndexList中
//向右边扫描
temp = mid+1;
while(true){
if(temp>arr.length-1||arr[temp]!=findValue){
break;
}
//否则就把temp放到resIndexList
resIndexList.add(temp);
temp++;
}
return resIndexList;
}
}
测试
List<Integer> resIndexList = binarySearch02(arr,0,arr.length,809);
System.out.println("resIndexList="+resIndexList);