查找算法(二):二分查找

本文详细介绍了二分查找的思路与实现,包括在无重复元素数组中的基本应用及处理重复元素的情况。通过递归方式,当目标值大于、小于或等于中间值时分别向右、向左或返回中间下标。对于重复元素,需要在找到目标值后继续扫描左右两侧以获取所有匹配下标。提供的代码示例展示了如何在Java中实现这两种情况的二分查找。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分查找的思路

1、将待查找的数组arr[]进行排序,这里进行二分查找的数组规定是有序的。接下来的讨论是基于升序的数组进行的。
2、确定待查找数组的中见下标 mid = (left + right) / 2;让中间值与待查找的目标值findVal进行比较。
3、分为以下几种情况:当findVal > arr[mid]时,则向右进行递归二分查找;
当findVal < arr[mid]时,则向左进行递归二分查找;
当findVal == arr[mid]时,则返回mid。
4、结束递归:当找到待查找值的下标就结束递归;或者虽然没找到findVal,但是当left > right时也得结束递归。

二分查找的代码实现

以下代码是针对所查找的数在数组中无重复的情况:

    /**
     *
     * @param arr 要查找的数组
     * @param left 左边的索引
     * @param right 右边的索引
     * @param findlVal 要查找的值
     * @return 如果找到返回下标,没有找到返回-1
     */
    public static int binarySearch(int[] arr,int left,int right,int findlVal) {
        if (left > right) {
            return -1;
        }
        int mid = (left + right) / 2;
        int midVal = arr[mid];
        if (findlVal > midVal) {//向右递归
            return binarySearch(arr, mid + 1, right, findlVal);
        } else if (findlVal < midVal) {//向左递归
            return binarySearch(arr, left, mid - 1, findlVal);
        } else {
            return mid;
        }
    }

以下是针对所查找的值在数组中有重复的情况,具体思路是,当findVal == arr[mid]时,需要从mid的左右两边分别扫描,将所有查找到的索引装入到一个动态数组中。

    public static List<Integer> binarySearch2(int[] arr, int left, int right, int findlVal) {
        if (left > right) {
            return new ArrayList<Integer>();//返回一个空的数组
        }
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findlVal > midVal) {//向右递归
            return binarySearch2(arr, mid + 1, right, findlVal);
        } else if (findlVal < midVal) {//向左递归
            return binarySearch2(arr, left, mid - 1, findlVal);
        } else {//fingVal == midVal 这里就需要进行左右两边扫描
        	//new一个动态数组用来存放索引
            List<Integer> resIndexlist = new ArrayList<Integer>();
            //向mid的左边进行扫描
            int temp = mid - 1;
            while(true){
                if (temp < 0 || arr[temp] != findlVal){//当越过左边界或者两数不相等时,退出循环
                    break;
                }
                resIndexlist.add(temp);
                temp -= 1;//继续向左扫描
            }
            //不要忘了把中间的索引加进去,因为向左向右扫描是基于findVal == arr[mid]
            resIndexlist.add(mid);

            //向右扫描
            temp = mid + 1;
            while(true){
                if (temp > arr.length -1 || arr[temp] != findlVal){//当越过右边界或者两数不相等时,退出循环
                    break;
                }
                resIndexlist.add(temp);
                temp += 1;//继续向右扫描
            }
            return  resIndexlist;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值