【考点 · 5级】二分查找,属于查找算法,核心思想:每次排除一半的搜索范围。
【说人话】想象你在字典里查一个词——你不会从第一页开始翻,而是直接翻到中间,判断目标在前半还是后半,然后继续折半。前提是数据必须有序(单调递增或递减)。
mid = (l + r) / 2 在 l+r 很大时可能整数溢出!安全写法是 mid = l + (r - l) / 2。另外 l 和 r 的更新是 l = mid + 1 和 r = mid - 1(不是 mid),否则死循环!
l <= r 而不是 l < r?nums 和一个目标值 target,用二分查找找到 target 在数组中的第一个出现位置(最左边)。如果不存在返回 -1。nums = [1, 2, 2, 2, 3, 4], target = 21(第一个 2 的下标是 1)
int lowerBound(int nums[], int n, int target) {
int l = 0, r = n - 1, ans = -1; // ans 记录最左边的下标
while (l <= r) {
int mid = l + (r - l) / 2;
if (nums[mid] >= target) { // 目标在左半边(含mid)
ans = mid; // 更新答案
r = mid - 1; // 继续往左找
} else {
l = mid + 1; // 目标在右半边
}
}
return ans;
}
// nums=[1,2,2,2,3,4], target=2 → 输出: 1
🔴 死循环:边界更新必须是 mid+1 / mid-1,不能写 l=mid / r=mid,否则 l==r 时不会前进。
🔴 整数溢出:(l+r)/2 当 l 和 r 都接近 INT_MAX 时会溢出,务必写成 l+(r-l)/2。
🔴 搞混两种二分:找"等于 target"用 l <= r 闭区间;找"第一个 ≥ target"(lower_bound)用 l < r 开区间模板也行,关键是理清自己要找什么。
🔴 忘记排序:二分查找的前提是数组有序!如果没排序,结果完全不可靠。