二分查找 / 折半查找 算法详解

88 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第二十二天,点击查看活动详情

前言:上一文大家了解到了查找算法,接下来给大家详细解说二分查找算法~

二分查找 / 折半查找

  • 必须是顺序的数组,若是无序的,则需要先排序(小到大 / 大到小)

思路

(以下是排序已为由小到大)

  1. 首先确定该数组的中间下标

    • mid = (left + right)/ 2
  2. 然后让需要查找的数 findValue 和 arr[mid] 进行比较

    1. findValue > mid[arr] :说明要查找的数在 mid 的右边,应该向右查找(向右递归查找)
    2. findValue < mid[arr] :说明要查找的数在 mid 的左边,应该向左查找(向左递归查找)
    3. findValue = mid[arr] :说明已经找到,则返回
  3. 退出递归

    1. 找到目标退出递归
    2. 找不到退出递归 (==left > right==)
/**
 * @author Kcs 2022/9/5
 */
public class BinarySearch {
    public static void main(String[] args) {
        //有序数组
        int[] arr = {0, 11, 22, 33, 44, 45, 55, 77, 88, 88, 88, 88, 99};
        // int index = binarySearch(arr, 0, arr.length - 1, 12);
        // System.out.println("index=" + index);
        List<Integer> integers = binarySearch2(arr, 0, arr.length - 1, 99);
        System.out.println(integers);
​
    }
​
    /**
     * 二分查找算法
     * @param arr 查找数组
     * @param left 左边索引
     * @param right 右边索引
     * @param findValue 查找的值
     * @return index
     */
    public static int binarySearch(int[] arr, int left, int right, int findValue) {
​
        //没有找到
        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;
        }
    }
​
    /**
     * 查找重复的值索引
     * @param arr
     * @param left
     * @param right
     * @param findValue
     * @return
     */
    public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int findValue) {
​
        //没有找到
        if (left > right) {
            return new ArrayList<Integer>();
        }
​
        //中间索引
        int mid = (left + right) / 2;
​
        //中间值
        int midValue = arr[mid];
​
        //判断递归的方向
        //向右
        if (findValue > midValue) {
            return binarySearch2(arr, mid + 1, right, findValue);
        } else if (findValue < midValue) {
            return binarySearch2(arr, left, mid - 1, findValue);
        } else {
            ArrayList<Integer> resIndexlist = new ArrayList<>();
            int temp = mid - 1;
            //向mid左边开始继续搜索
            while (true) {
                //退出
                if (temp < 0 || arr[temp] != findValue) {
                    break;
                }
                resIndexlist.add(temp);
                temp -= 1;
            }
            resIndexlist.add(mid);
            //向mid右边继续搜索
            temp = mid + 1;
            while (true) {
                if (temp > (arr.length - 1) || arr[temp] != findValue) {
                    break;
                }
                resIndexlist.add(temp);
                temp += 1;
            }
            return resIndexlist;
        }
    }
}