二分查找算法

二分查找前提

进行二分查找的数组是有序数组

二分查找算法思路

  • 首先确定该数组的中间下标 mid = (left+right)/2
  • 然后让需要查找的数和arr[mid]进行比较
    • findVal > arr[mid] 说明你要查找的数在mid的右边,因此需要递归向右进行查找
    • findVal < arr[mid] 说明你要查找的数在mid的左边,因此需要递归向左进行查找
    • findVal = arr[mid] 说明找到,返回

注意:
使用递归要特别注意结束条件,不然就会成为死递归

  • 找到就结束递归
  • 遍历完整个数组,仍然没有找到findVal,也需要结束递归 当left>right时就结束了

代码实现

实现返回找到的第一个值的下标

 public static void main(String[] args) {
        int[] arr = {1, 8, 10, 89, 1000, 1234};
        int index = binarySearch(arr, 0, arr.length - 1, 89);
        System.out.println("index = "+index);
    }

    /**
     * @param arr     数组
     * @param left    左边的下标
     * @param right   右边的下标
     * @param findVal 查找的值
     * @return 返回查找到的第一个下标
     */
    private static int binarySearch(int[] arr, int left, int right, int findVal) {
        if (findVal < arr[left] || findVal > arr[right] || left > right) { //没有找到
            return -1;
        }
        int mid = (left + right) / 2;
        if (findVal < arr[mid]) { //findVal小于中间值 ,则说明在左边,需要左递归
            return binarySearch(arr, left, mid - 1, findVal);
        } else if (findVal > arr[mid]) { // findVal大于中间值,需要向右递归
            return binarySearch(arr, mid + 1, right, findVal);
        } else { //相等
            return mid;
        }
    }

返回多个下标

如果数组中待查找的元素有多个,这时就需要返回多个下标.核心思想就是借助于上面查找到的一个下标,向左右两边依次查找,是否还有与findVal相等的值

public class BinarySearch {
    public static void main(String[] args) {
        int[] arr = {1, 8, 10, 89,1000, 1000, 1000, 1000, 1000, 1234};
        List<Integer> indexList = binarySearch2(arr, 0, arr.length - 1, 1000);
        System.out.println("indexList = " + indexList);
    }

    /**
     * @param arr     数组
     * @param left    左边的下标
     * @param right   右边的下标
     * @param findVal 待查找的值
     * @return 返回查找元素下标的集合
     */
    private static List<Integer> binarySearch2(int[] arr, int left, int right, int findVal) {
        //递归结束条件
        if (findVal < arr[left] || findVal > arr[right] || left > right) {
            return new ArrayList<Integer>();
        }
        List<Integer> indexList = new ArrayList<>();
        int mid = (left + right) / 2;
        if (findVal < arr[mid]) {
            return binarySearch2(arr, left, mid - 1, findVal);
        } else if (findVal > arr[mid]) {
            return binarySearch2(arr, mid + 1, right, findVal);
        } else {
            //找到一个下标mid之后,需要像mid的左右两边进行遍历,把值相等的下标,添加到集合中返回
            int temp = mid - 1;
            //向左边查找
            while (true) {
                if (temp < 0 || arr[temp] != findVal) {
                    break;
                }
                indexList.add(temp);
                temp -= 1;
            }

            //添加mid
            indexList.add(mid);

            temp = mid + 1;
            //向右边查找
            while (true) {
                if (temp > arr.length - 1 || arr[temp] != findVal) {
                    break;
                }
                indexList.add(temp);
                temp += 1;
            }

            return indexList;
        }
    }

原文地址:https://www.cnblogs.com/liuzhidao/p/13835775.html