二分查找及查找左、右边界

目录

二分查找

概念:

详细举例:

那么问题来了

实现代码:

查找左右边界:

概念:

举例:

编写思路:

实现代码:


二分查找

概念:

通过将一组“有序”的‘组’不断的一分为二的方法,快速在这个‘组’中找到想要查找的数

详细举例:

在‘组’【0,1,2,3,4,5,6,7,8】中,想要快速的找到8的位置。接下来就用二分查找法进行查找。

在0-8位置的查找范围中,找到中间位置的元素,与查找元素8进行比较。

得到中间元素4小于查找元素8

所以根据‘序’,知道查找元素8在查找范围0-8中的右半部分

所以可以缩小查找范围,知道新范围在4右边的位置5,到8是我们新的查找范围

在新范围5-8中,找到中间位置的元素,与查找元素8进行比较。

得到中间元素6小于查找元素8

所以根据‘序’,知道查找元素8在查找范围5-8中的右半部分

所以可以缩小查找范围,知道新范围在6右边的位置7,到8是我们新的查找范围

在新范围7-8中,找到中间位置的元素,与查找元素8进行比较。

得到中间元素7小于查找元素8

所以根据‘序’,知道查找元素8在查找范围7-8中的右半部分

所以可以缩小查找范围,知道新范围在7右边的位置8,到8是我们新的查找范围

在新范围8-8中,找到中间位置的元素,与查找元素8进行比较。

得到中间元素8等于查找元素8

所以返回8的位置,即8

至此,查找完毕

那么问题来了

中间元素怎么找的?为什么5-8的中间元素是6呢?

计算方法为:(左范围+右范围)/2

所以,这就解释了为什么是6

这里需要注意,推荐使用“左范围+(右范围-左范围)/2”

这样可以避免加法运算可能导致的溢出问题

实现代码:

public static int binarySearch(int[] arr, int search) {
        int left = 0, mid, right = arr.length - 1;

        while (left <= right) {
            mid = left + (right - left) / 2;
            if (arr[mid] == search)
                return mid;
            else if (arr[mid] < search) {
                left = mid + 1;
            } else if (arr[mid] > search) {
                right = mid - 1;
            }
        }
        return -1;
    }

查找左右边界:

概念:

查找此数在数组出现的为最左边的位置即查找左边界,右边界同理

举例:

我想要在arr=[1,2,2,2,2,4,7,8,9,99]中查找2,这个时候会看见好几个2,此时arr[1]是2在数组的左边出现的,所以arr[1]就是我要找的左边界。右边界同理。

编写思路:

通过二分查找的“缩范围”的思想,将范围尽量向左缩小,即遇到2的时候,我往左缩一下范围看看,看看此时找到的2的左侧的范围,还有没有2了,有就接着缩,没有就证明此时的是要找的左边界了,就可以输出这个位置了

实现代码:

public static int binarySearchLeft(int[] arr, int search) {
        int left = 0, mid, right = arr.length - 1;

        while (left <= right) {
            mid = left + (right - left) / 2;
            if (arr[mid] == search) {
                right = mid - 1;
            } else if (arr[mid] < search) {
                left = mid + 1;
            } else if (search < arr[mid]) {
                right = mid - 1;
            }
        }
        if (left >= arr.length || arr[left] != search)
            return -1;
        return left;
    }

此时需要在后面加上if语句进行越界及未找到的判断,是则返回-1;反之返回对应下标。

查找右边界源码:

int binarySearchRight(int[] arr, int search) {
        int left = 0, right = arr.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] < search) {
                left = mid + 1;
            } else if (arr[mid] > search) {
                right = mid - 1;
            } else if (arr[mid] == search) {
                left = mid + 1;
            }
        }
        if (right < 0 || arr[right] != search)
            return -1;
        return right;
    }

与查找左边界同理,此即向右边缩小查找范围

学习源于、超细致详解:为了学会二分搜索,我作了首诗 - 知乎,膜拜大佬.jpg

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿星_007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值