二分查找的基本概念
二分查找是一种在有序数组中查找特定元素的高效算法。通过每次将搜索范围减半,时间复杂度可降至O(log n),远优于线性查找的O(n)。
二分查找的实现
标准二分查找的实现需要维护三个指针:左边界left、右边界right和中间点mid。每次迭代根据mid处的值与目标值的比较结果调整搜索范围。
int binarySearch(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) return mid;
if (nums[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}
边界条件处理
二分查找的边界条件容易出错。常见问题包括:
- 循环条件应为
left <= right而非left < right,否则可能漏查边界元素 - 计算
mid时使用left + (right - left) / 2可避免整数溢出 - 更新边界时需明确
mid ± 1,防止死循环
变种与应用
二分查找有多种变体,适用于不同场景:
- 查找第一个大于等于目标的元素
int lowerBound(vector<int>& nums, int target) {
int left = 0, right = nums.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) left = mid + 1;
else right = mid;
}
return left;
}
- 在旋转有序数组中查找
int searchRotated(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) return mid;
if (nums[left] <= nums[mid]) {
if (nums[left] <= target && target < nums[mid]) right = mid - 1;
else left = mid + 1;
} else {
if (nums[mid] < target && target <= nums[right]) left = mid + 1;
else right = mid - 1;
}
}
return -1;
}
性能优化
现代CPU的缓存机制使二分查找的实际性能可能优于理论预期。可通过以下方式优化:
- 使用迭代而非递归减少函数调用开销
- 对小型数组切换为线性查找
- 使用位运算替代除法计算
mid
常见错误与调试
调试二分查找时建议:
- 打印每次迭代的
left、right和mid值 - 测试空数组、单元素数组等边界情况
- 验证数组中存在重复元素时的行为
数学基础
二分查找的正确性基于循环不变式:
- 初始化:首次循环前,目标值在
[left, right]范围内 - 保持:每次迭代后目标值仍在新的
[left, right]范围内 - 终止:当
left > right时,区间为空说明目标不存在
时间复杂度推导: [ T(n) = T(n/2) + O(1) ] 通过主定理可得: [ T(n) = O(\log n) ]

506

被折叠的 条评论
为什么被折叠?



