二分查找的边界条件
二分查找看起来简单,真正容易出错的是边界。循环条件、区间开闭、返回值含义只要有一处不一致,就会出现死循环或漏掉答案。
先确定区间语义
二分查找常见两种写法:闭区间 [left, right] 和左闭右开区间 [left, right)。
闭区间写法中,left 和 right 都是可能答案:
1 | int left = 0, right = nums.length - 1; |
左闭右开写法中,right 不属于搜索范围:
1 | int left = 0, right = nums.length; |
两种写法都可以,关键是不要混用。
查找具体值与查找边界
普通二分查找只关心目标值是否存在;边界二分关心第一个满足条件的位置。例如“第一个大于等于 target 的位置”,可以把条件写成:
1 | if (nums[mid] >= target) right = mid; |
循环结束后,left 就是候选位置。此时还要检查是否越界,以及该位置是否真的满足条件。
避免中点溢出
(left + right) / 2 在极端情况下可能整数溢出。更稳妥的写法是:
1 | int mid = left + (right - left) / 2; |
这也是二分查找里最常见的细节之一。
小结
二分查找的核心不是“每次砍半”,而是让区间语义始终一致。先写清楚区间,再写循环条件,最后确认返回值含义,错误会少很多。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 xiaobai050!