二分查找核心原理
二分算法的本质并非单纯依赖数组有序,关键在于具有二段性。即存在一个分界点,能将数组划分为满足特定条件的两部分,从而通过一次比较排除一半的搜索空间。
循环结束条件
通常采用 left <= right。因为当 left == right 时,区间内仍有一个未知元素,需要与目标值再次比较确认是否存在。
时间复杂度 O(logN) 相比 O(N) 效率提升显著。在 int 范围内,O(N) 最多需比较 4×10^9 次,而 O(logN) 仅需约 32 次。
数据溢出防护
计算中间值时,(left + right) / 2 在极端情况下可能溢出。推荐使用 left + (right - left) / 2,利用起始值加偏移量的方式避免两数相加超出范围。mid 计算是否加 1 取决于具体场景,奇数长度数组结果一致,偶数长度时分别指向左中位或右中位,不影响最终收敛。
LeetCode 704. 二分查找
这是最基础的模板应用。while(left <= right) 配合 mid = (left + right) / 2 即可解决标准查找问题。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) left = mid + 1;
else if (nums[mid] > target) right = mid - 1;
else return mid;
}
return -1;
}
};
LeetCode 34. 查找元素的第一个和最后一个位置
此题要求找到目标值的边界。虽然数组有序,但我们需要更精细的控制。
查找左端点
当 nums[mid] < target 时,左端点一定在右侧,更新 left = mid + 1。
当 nums[mid] >= target 时,mid 可能是左端点,不能舍弃,更新 right = mid。
注意循环条件用 ,这样当 时即为结果,避免死循环。


