You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

二分查找右边界应设为nums.length还是nums.length-1?

二分查找的右边界初始值选择本质是搜索区间定义的区别,只要和边界收缩逻辑完全匹配就不会出问题,二者没有强制的使用场景要求,只需要全程遵循同一套规则即可。

1. 两种右边界对应的区间定义

  • 右边界初始值为 r = nums.length - 1:对应左闭右闭区间 [l, r],搜索范围包含r位置本身,r是合法的数组下标,所有循环中计算得到的中间值m都不会超过数组最大下标
  • 右边界初始值为 r = nums.length:对应左闭右开区间 [l, r),搜索范围只到r的前一个位置,r本身是不参与搜索的非法下标,所有逻辑中都不能直接访问nums[r]

你提供的第二版代码报错的核心原因是把两套规则混用:用了左闭右开的初始右边界,但收缩逻辑完全照搬左闭右闭的规则,当target大于数组所有元素时,计算出的中间值m会等于nums.length,直接访问nums[m]就会触发数组越界异常。

2. 两种写法的正确实现(以查找有序数组中target最后一次出现的下标为例)

2.1 左闭右闭写法(r = nums.length - 1)

这是你第一版的正确实现,逻辑更直观,不易出错:

public int binarySearchLarger(int[] nums, int target) {
    int l = 0;
    int r = nums.length - 1;
    while (l < r) {
        // 向上取整避免l和r相邻时进入死循环
        int m = l + (r - l + 1) / 2;
        if (nums[m] <= target) {
            // m位置符合要求,保留为左边界,继续向右找更靠后的匹配项
            l = m;
        } else {
            // m位置比target大,不可能是解,右边界移动到m-1
            r = m - 1;
        }
    }
    return nums[l] == target ? l : -1;
}

2.2 左闭右开写法(r = nums.length)

如果选择r = nums.length的初始值,必须配套修改边界收缩逻辑,不能访问右边界下标:

public int binarySearchLarger(int[] nums, int target) {
    int l = 0;
    int r = nums.length;
    while (l < r) {
        int m = l + (r - l) / 2;
        if (nums[m] > target) {
            // m位置不符合要求,右边界移动到m(开区间不包含m,无需减1)
            r = m;
        } else {
            // m位置符合要求,继续向右找更靠后的匹配项
            l = m + 1;
        }
    }
    // 循环结束时l==r,最后一个匹配项的位置是l-1
    l--;
    return l >= 0 && nums[l] == target ? l : -1;
}

3. 选择建议

两种写法没有性能差异,根据个人编码习惯选择即可:

  • 刚接触二分查找更推荐用左闭右闭写法,逻辑更贴合直觉,不容易出现越界问题
  • 如果你习惯和JavaArrays.binarySearch、Pythonbisect模块等内置二分方法的规则对齐,可以选择左闭右开写法

内容的提问来源于stack exchange,提问作者yueran zhang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 13:54:03