二分查找算法(java实现)
二分查找 又叫折半查找,是一种简单又快速的查找算法 适用于(有序列表)
每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为0。二分查找是一种非常非常高效的查询算法,时间复杂度为O(logn)。
算法前提:
- 必须采用顺序存储结构
- 必须按关键字大小有序排列
例如:
请对一个有序数组 arr 进行 二分查找 {1,8, 10, 89, 1000, 1000, 1234} ,输入一个数看看该数组是否存在此数,并且求出下标,如果没有就提示"没有这个数",有多个相同的数值时,如何将所有的数值都查找到,比如这里的 1000.
思路分析:(递归实现)
- 确定数组arr的中间的下标:
mid = (left + right) / 2 | left为数组最左边下标为 0,right为数组最右边下标 为arr.length - 1
- 将待查找的数 findVal 与 数组中间的值 arr[mid]比较:
当 findVal > arr[mid] 时,说明 待查找的数 findVal 在 arr[mid] 的 右边 ,需要 递归向右 继续查找。
当 findVal < arr[mid] 时,说明 待查找的数 findVal 在 arr[mid] 的 左边 ,需要 递归向左 继续查找。
当 findVal = arr[mid] 时,说明 待查找的数 findVal 为 arr[mid] 返回改值下标
-
递归结束条件:
找到值 结束递归
递归查找完整个数组,还未找到 待查找的数 findVal ,也结束递归 (当 left > right 时)
代码实现:
import java.util.ArrayList; import java.util.List; public class BinarySearch { public static void main(String[] args) { int arr[] = { 1, 8, 10, 89,1000,1000, 1234 }; List<Integer> resIndexList = binarySearch(arr, 0, arr.length - 1, 1000); System.out.println("resIndexList=" + resIndexList); } // 二分查找算法 /** * * @param arr * 数组 * @param left * 左边的索引 * @param right * 右边的索引 * @param findVal * 要查找的值 * @return 如果找到就返回下标,如果没有找到,就返回 -1 */ public static List<Integer> binarySearch(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 binarySearch(arr, mid + 1, right, findVal); } else if (findVal < midVal) { // 向左递归 return binarySearch(arr, left, mid - 1, findVal); } else { List<Integer> resIndexList = new ArrayList<>(); int temp = mid-1; while(true) { if (temp < 0|| arr[temp] != findVal) { break; } resIndexList.add(temp); temp -= 1; } resIndexList.add(mid); temp = mid+1; while(true) { if (temp > arr.length -1|| arr[temp] != findVal) { break; } resIndexList.add(temp); temp += 1; } return resIndexList; } } //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; // } // // } }