二分查找(Java)
1.概念
二分查找(Binary Search)也叫作折半查找。二分查找有两个要求,一个是数列有序,另一个是数列使用顺序存储结构(比如数组)
2.思路分析
1.首先确定数组的中间下标:mid=(left+right)/2
2.然后让需要查找的数findVal和arr[mid]比较
2.1 findVal > arr[mid] 说明要查找的数在 mid 右边,因此向右递归查找
2.2 findVal < arr[mid] 说明要查找的数在 mid 左边,因此向左递归查找
2.3 findVal = arr[mid] 说明找到,既返回
3.何时结束递归?
3.1 找到就结束递归
3.2 递归完整个数组仍然没找到findVal,也需要结束递归(left>right就需要结束)
3.代码
package DataStructuresAlgorithm.Search;
public class BinarySearch {
public static void main(String[] args) {
int[] arr = new int[]{1, 8, 10, 89, 1000, 1234};
int resIndex = binarySearch(arr, 0, arr.length - 1, 88);
System.out.println(resIndex);
}
/**
* @param arr 数组
* @param left 左边的索引
* @param right 右边的索引
* @param findVal 需要查找的值
* @author ZJ
* Description 二分查找
* date 2022-05-13 10:14:59 10:14
*/
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;
}
}
}
但是,如果一个数组中有很多个相同的数,比如上面的数组有4个1000,查找后只会返回第一个1000的下标,代码还可以改进
1.找到第一个匹配的索引值 mid 的时候,不要马上返回
2.向 mid 索引值 的左边扫描,将所有与 findVal 相等的元素 的下标 索引返回,加入到ArrayList
3.向 mid 索引值 的右边扫描,将所有与 findVal 相等的元素 的下标 索引返回,加入到ArrayList
/**
* @param arr
* @param left
* @param right
* @param findVal
* @author ZJ
* Description 二分查找(查找值有多个的话,返回一个List)
* date 2022-05-13 10:36:28 10:36
*/
public static ArrayList<Integer> binarySearchMore(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];
ArrayList<Integer> resIndexList = new ArrayList<>();
if (findVal > midVal) {//向右递归
return binarySearchMore(arr, mid + 1, right, findVal);
} else if (findVal < midVal) {
return binarySearchMore(arr, left, mid - 1, findVal);
} else {
//向 mid 索引值 的左边扫描,将所有与 findVal 相等的元素 的下标 索引返回,加入到ArrayList
int temp = mid - 1;
while (true) {
if (temp < 0 || findVal != arr[temp]) {
break;
}
//否则,就把temp放到ArrayList中
resIndexList.add(temp);
temp -= 1;//temp左移
}
resIndexList.add(mid);
//向 mid 索引值 的右边扫描,将所有与 findVal 相等的元素 的下标 索引返回,加入到ArrayList
temp = mid + 1;
while (true) {
if (temp > arr.length - 1 || findVal != arr[temp]) {
break;
}
//否则,就把temp放到ArrayList中
resIndexList.add(temp);
temp += 1;//temp右移
}
}
return resIndexList;
}
完整代码
package DataStructuresAlgorithm.Search;
import java.util.ArrayList;
public class BinarySearch {
public static void main(String[] args) {
int[] arr = new int[]{1, 8, 10, 89, 1000, 1000, 1000, 1000, 1234};
// int resIndex = binarySearchOne(arr, 0, arr.length - 1, 88);
// System.out.println(resIndex);
ArrayList<Integer> reIndexList = binarySearchMore(arr, 0, arr.length - 1, 1000);
System.out.println(reIndexList);
}
/**
* @param arr 数组
* @param left 左边的索引
* @param right 右边的索引
* @param findVal 需要查找的值
* @author ZJ
* Description 二分查找(只返回一个)
* date 2022-05-13 10:14:59 10:14
*/
public static int binarySearchOne(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 binarySearchOne(arr, mid + 1, right, findVal);
} else if (findVal < midVal) {
return binarySearchOne(arr, left, mid - 1, findVal);
} else {
return mid;
}
}
/**
* @param arr
* @param left
* @param right
* @param findVal
* @author ZJ
* Description 二分查找(查找值有多个的话,返回一个List)
* date 2022-05-13 10:36:28 10:36
*/
public static ArrayList<Integer> binarySearchMore(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];
ArrayList<Integer> resIndexList = new ArrayList<>();
if (findVal > midVal) {//向右递归
return binarySearchMore(arr, mid + 1, right, findVal);
} else if (findVal < midVal) {
return binarySearchMore(arr, left, mid - 1, findVal);
} else {
//向 mid 索引值 的左边扫描,将所有与 findVal 相等的元素 的下标 索引返回,加入到ArrayList
int temp = mid - 1;
while (true) {
if (temp < 0 || findVal != arr[temp]) {
break;
}
//否则,就把temp放到ArrayList中
resIndexList.add(temp);
temp -= 1;//temp左移
}
resIndexList.add(mid);
//向 mid 索引值 的右边扫描,将所有与 findVal 相等的元素 的下标 索引返回,加入到ArrayList
temp = mid + 1;
while (true) {
if (temp > arr.length - 1 || findVal != arr[temp]) {
break;
}
//否则,就把temp放到ArrayList中
resIndexList.add(temp);
temp += 1;//temp右移
}
}
return resIndexList;
}
}
版权声明:本文为qq_52374468原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。