通俗易懂讲解二分查找

这篇博客探讨了二分查找算法在寻找目标元素时如何通过排除非目标元素来缩小搜索范围。当循环条件为`left < right`时,算法会在区间[left, right]内进行查找。博客指出,当left等于right时,可能已找到目标元素。此外,文章强调了向下取整导致的死循环问题,建议在计算中间索引时使用向上取整以避免错误。博客还提醒读者注意left和right作为闭区间的性质,确保在划分区间时它们能取到值。

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

此种二分查找的思路并不是为了直接去查找目标元素,而是不断地去排除不是目标的元素,退出循环时,数组中只有一个元素,那么这个元素很大可能性是目标元素,如果题目已经告诉你数组中有一个目标元素,那么这个铁定是目标元素

public class Solution {
   
    public int search(int[] nums, int target) {
        int len = nums.length;

        int left = 0;
        int right = len - 1;
        // 目标元素可能存在在区间 [left, right]
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                // 下一轮搜索区间是 [mid + 1, right]
                left = mid + 1;
            } else {
                // 下一轮搜索区间是 [left, mid]
                right = mid;
            }
        }

        if (nums[left] == target) {
            return left;
        }
        return -1;
    }
}

循环可以继续的条件是 while (left < right) ,这是一个很重要的标志。为什么是严格小于呢?我们上一节说过,当 left == right ,左边界和右边界重合的时候,区间里只有 1 个元素时候,二分查找的逻辑还需要继续下去;而现在大家看到的这个解法在 left == right 重合的时候就退出了循环,这一点表示区间里只剩下一个元素的时候,有可能这个元素就是我们要找的那个元素。这一点与二分查找算法的思路 2(在循环体中排除元素)是一致的:排除了所有错误的答案,如果题目告诉我们只有 1 个目标元素,那么剩下的这个元素就一定是目标元素。

第二点

关于向上取整和向下取整。
有关死循环的问题
如果是
int mid = left + (right - left)/2; 则是向下取整
这时如果你的判断时

    while (left < right) {
        int mid =left +  (right - left) / 2;
        if (nums[mid] > target) {
            // mid 以及 mid 的右边一定不是目标元素最后一次出现的位置
            // 下一轮搜索的区间是 [left, mid - 1]
            right = mid - 1;
        } else {
            // 下一轮搜索的区间是 [mid, right]
            left = mid;
        }
    }
    return left;

如果最后只有两个元素,由于是向下取整,导致mid值是在left位置,但你最后判断的结果是left还是等于mid,那说明进入了死循环。

我们只需要记住一个结论:当看到分支是 left = mid; 和 right = mid - 1; 的时候,在计算中间数的索引的时候要向上取整。

left = mid+1 或者 right = mid-1

这里的加一和减一都要非常的考虑仔细,并不是随随便便就去 加一和减一的, 因为这里的 left 和 right 都是闭区间,这里的left 和 right 在你把区间一分为二的时候,这里的left 和 right 要能够取到值,记住,一定要能取到值,不然的话,就不是闭区间了,而是开区间了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值