经典二分查找的分析

本文深入探讨了二分查找算法,这是一种在有序数组中快速查找元素的高效方法。通过举例说明,解释了二分查找的逻辑和边界处理的重要性。文章指出,正确实现二分查找需要注意找中点的技巧、循环条件以及更新指针的方式,以避免溢出和死循环。此外,还讨论了二分查找的局限性,强调数据需有序且支持随机访问,适合使用在数组中。
摘要由CSDN通过智能技术生成

前言

对于二分查找,也可以叫折半查找,你一定不会陌生,以前应该也有玩过猜价格的有戏,让你在某个价格区间内,猜某个商品的价格,如果没猜到就告诉你是猜多了还是猜少了,然后让你继续猜,这其实就可以运用到二分查找的方式来最快的猜到那个价格。

高效的查找方式

二分查找是一种非常高效的查找方式,对于一个2的32次方的数来说,大约有42亿之多,但由于二分查找拥有logn的时间复杂度,所以也就最多只需要32次就能查找出结果。

简单但不容易

二分查找虽然思路非常简单,但是要想写出正确的二分查找,其实并没有那么容易,这点我相信只要写过的都应该能够体会到,主要问题就在于边界的处理。

代码实现

    public int binarySearch(int[] nums, int target) {
        int l = 0;
        int r = nums.length - 1;
        while (l <= r) {
            //找到中点,这样写l + ((r - l) >> 1) 等同于 (l+r)/2,但是可以防止l+r溢出
            int mid = l + ((r - l) >> 1);
            //如果等于目标值直接返回
            if (nums[mid] == target) {
                return mid;
            }
            //如果中间点大于目标值,则找左半边,否则找右半边
            if (nums[mid] > target) {
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
        //找不到返回-1
        return -1;
    }

容易出问题的地方

  • 问题1:找中点,l + ((r - l) >> 1)对于奇数来说,找的刚好就是中间的位置,对于偶数来说,找的是靠左边的位置。
    这样写可以防止(l+r)/2时,l+r可能会溢出的问题。

  • 问题2:while (l <= r),注意这里是 l<=r,而不是l<r
    如果写成l<r,就会把第一个和最后一个位置的元素漏掉。

  • 问题3:r和l的更新,应该是mid-1或者是mid+1
    如果直接更新为mid,则可能会发生死循环,比如把r = mid-1,直接写成r = mid,然后在1,2,3,5,6,7,8,查找4,就会发生死循环。因为最后会算出l==r(都等于3),mid等于3,并且nums[mid](5)) > target(4),然后r被无限赋值为3。

限制条件

虽然二分查找非常的快,但也是有一定的局限性的,其中最大的问题就是要求待查找的数据是有序的,其次要求支持高效的随机访问,如果每一次定位中间位置都需要花费额外的时间去查找,那就不能说其整个时间复杂度是logn的了,最后既然要求有序还要支持随机访问,那能想到的数据结构就是数组了,所以一般对于二分查找来说,还需要连续的内存空间,如果二分查找的数据量非常的大,可能对内存的要求也比较苛刻。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码拉松

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

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

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

打赏作者

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

抵扣说明:

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

余额充值