📢 欢迎来到万事技术论坛!本站仅讨论合法编程技术话题,严禁外挂/作弊/黑产/盗版内容,违者封号。

精华二分查找的边界问题:90% 的人写错过

captain_algo 活跃会员

二分思路人人会讲,写出来 bug 一堆。核心是区间定义要一以贯之。

两种写法,选一个别混

闭区间 [left, right]

def binary_search(nums, target):
    left, right = 0, len(nums) - 1        # 右边界能取到
    while left <= right:                  # 等号:区间非空
        mid = left + (right - left) // 2  # 防溢出
        if nums[mid] < target:
            left = mid + 1                # mid 已排除
        elif nums[mid] > target:
            right = mid - 1
        else:
            return mid
    return -1

半开区间 [left, right)

def lower_bound(nums, target):
    """返回第一个 >= target 的下标"""
    left, right = 0, len(nums)            # 右边界取不到
    while left < right:                   # 不能加等号
        mid = left + (right - left) // 2
        if nums[mid] < target:
            left = mid + 1
        else:
            right = mid                   # 注意不是 mid-1
    return left

三个最常错的点

  1. mid = (left + right) // 2 可能溢出:其他语言里是两个 int 相加溢出,用 left + (right - left) // 2 是通用好习惯;
  2. while 里加不加等号取决于区间是否闭合,混用必死循环或漏答案;
  3. right = mid 还是 mid - 1 同样取决于区间定义。

有重复元素怎么办

lower_bound 找第一个 >= target,upper_bound 找第一个 > target,两者配合就能数出 target 出现次数:

count = upper_bound(nums, target) - lower_bound(nums, target)

什么时候能用二分

不一定非要有序数组。只要能构造出一个单调的判定条件就能二分:

  • 「吃掉这堆香蕉最少要几小时」(单调:速度越快时间越短)
  • 「在 D 天内运完货物,船的最小载重」
  • 「求平方根,保留整数部分」

这类叫二分答案,比在数组里找数更常考。

建议只背 lower_bound 那套半开区间写法,左闭右闭容易在边界上纠结。

楼主 · 2026-09-28 13:21 · 浏览 6
yuki 进阶会员

只背 lower_bound 那套的建议太对了。我之前两种写法混着背,笔试的时候一紧张就写错边界,现在统一用半开区间再没出过错。

1楼 · 2026-09-28 13:21
登录 后即可参与回复。