二分查找算法

  • 二分查找算法介绍
  • 二分查找算法的思路分析
  • 二分查找算法(非递归)代码实现
  • 二分查找算法(递归)代码实现
    • 查找数组中只有一个结果的
    • 查找数组中有多个结果的

1. 二分查找算法(非递归)介绍

  • 二分查找法只使用从有序的数列中进行查找(比如数字或字母等),将数列排序后再进行查找
  • 二分查找的运行时间为O(log2 n),即查找到的目标位置最多只需要 log2 n 步 。

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],说明找到,就返回

  • 什么时候结束递归或循环
  1. 找到就结束
  2. 递归完整个数组,仍没有找到,当left > right 就退出

3. 二分查找算法(非递归)代码实现

public class BinarySearchNoRecur {
    public static void main(String[] args) {
        //测试
        int[] arr = {1,3,8,10,11,67,100};
        int index = binarySearch(arr,9);
        System.out.println("index=" + index); //
    }

    /**
     *  二分查找的非递归实现
     * @param arr 待查找的数组,arr是升序排序
     * @param target 需要查找的数
     * @return 返回对应下标,-1表示没有找到
     */
    public static int binarySearch(int[] arr,int target){
        int left = 0;
        int right = arr.length - 1;
        while(left <= right){ //说明可以继续查找
            int mid = (left + right) / 2;
            if(arr[mid] == target){
                return mid;
            }else if(arr[mid] > target){
                right = mid - 1; //需要左移查找
            }else if(arr[mid] < target){
                left = mid + 1; //需要向右边查找
            }
        }
        return -1;
    }

}

4.二分查找算法(递归)代码实现

4.1查找数组中只有一个结果的

 /**
     * 二分查找法(只能找到一个结果)
     * @param arr 数组
     * @param left 左边的索引
     * @param right 右边的索引
     * @param findVal 要查找的值
     * @return 如果找到就返回下标,如果没有找到,就返回-1
     */
    public static int binarySearch(int[] arr,int left,int right,int findVal){
        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.2 查找数组中有多个结果的

//将有序数组中的所有数值都查找到
    //思路:
    //1. 在找到 mid 索引值,不要马上返回
    //2. 向 mid 索引的左边扫描,将所有满足1000 的元素的下标,加入到集合ArrayList
    //3. 向 mid 索引的右边扫描, 将所有满足1000 的元素的下标,加入到集合 ArrayList
    //4. 返回ArrayList
    public static List binarySearch2(int[] arr, int left, int right, int findVal){
        if(left > right){
            return new ArrayList<>();
        }
        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 { //找到了
            List resIndexList = new ArrayList<>();
            //向 mid 索引的左边扫描,将所有满足1000 的元素的下标,加入到集合ArrayList
            int temp = mid - 1;
            while (true){
                if(temp < 0 || arr[temp] != findVal){
                    break;
                }
                //否则,就把temp放入 resIndexList
                resIndexList.add(temp);
                temp -= 1; //将temp 左移
            }
            resIndexList.add(mid);
            //向 mid 索引的右边扫描, 将所有满足1000 的元素的下标,加入到集合 ArrayList
            temp = mid + 1;
            while (true){
                if(temp > arr.length-1 || arr[temp] != findVal){
                    break;
                }
                //否则,就把temp放入 resIndexList
                resIndexList.add(temp);
                temp += 1; //将temp 左移
            }
            return resIndexList;
        }

你可能感兴趣的:(二分查找算法)