
二分查找的右边界应设为 array.length - 1(即最后一个有效索引),而非 array.length;后者虽在部分输入下看似“能运行”,但会因越界访问导致 ArrayIndexOutOfBoundsException,违反数组索引安全原则。
二分查找的右边界应设为 `array.length - 1`(即最后一个有效索引),而非 `array.length`;后者虽在部分输入下看似“能运行”,但会因越界访问导致 `arrayindexoutofboundsexception`,违反数组索引安全原则。
在实现二分查找时,边界定义直接决定算法的正确性与健壮性。核心原则是:start 和 end 始终表示合法的、可访问的数组索引范围。Java 中数组索引从 0 开始,长度为 n 的数组,其有效索引为 0, 1, ..., n−1。因此,初始右边界 end 必须为 numbers.length - 1 —— 这是最后一个元素的下标。
若错误地设为 end = numbers.length(例如对长度为 10 的数组设 end = 10),虽然循环条件 start
// 错误示范:end = numbers.length
int[] arr = {1, 2, 4, 6, 8, 10, 12, 14, 18, 20}; // length = 10
int start = 0, end = 10; // ❌ 越界起点
// 当搜索 key = 24 时,某次迭代可能出现:
// start = 9, end = 10 → mid = (9 + 10) / 2 = 9(暂无问题)
// 接着 numbers[9] = 20 < 24 → start = mid + 1 = 10
// 此时 start = 10, end = 10 → mid = 10
// → numbers[10] 触发 ArrayIndexOutOfBoundsException!
而正确初始化 end = numbers.length - 1(即 9)后,mid 永远不会超出 [0, 9] 范围,循环在 start > end(如 start = 10, end = 9)时自然终止,返回 -1 表示未找到,全程无越界风险。
✅ 正确写法(推荐):
public static int bsearch(int[] numbers, int key) {
int start = 0;
int end = numbers.length - 1; // ✅ 安全:指向最后一个有效索引
while (start <= end) {
int mid = start + (end - start) / 2; // 更优:避免 start+end 整数溢出
if (numbers[mid] == key) {
return mid;
} else if (numbers[mid] < key) {
start = mid + 1;
} else {
end = mid - 1;
}
}
return -1;
}⚠️ 注意事项:
- 永远不要用 numbers.length 作为 end 初始值:它不是索引,而是元素个数;
- 推荐使用 start + (end - start) / 2 计算 mid:防止大数组下 start + end 溢出(尤其在其他语言或长整型场景中);
- 边界更新需严格匹配逻辑:start = mid + 1 和 end = mid - 1 确保每次迭代都排除已判定无效的位置;
- 测试务必覆盖边界用例:如搜索小于最小值、大于最大值、不存在的中间值,验证鲁棒性。
总结:end = length - 1 不是“约定俗成”,而是由数组索引本质决定的必要约束。坚持这一原则,才能写出零越界、可验证、可维护的二分查找实现。










