1. 基础二分查找(LeetCode 704)
核心思路
二分算法通常被认为要求数组有序,但更严谨的说法是数据必须具备'二段性',即存在一个分界点能将数组分为两部分。
关键细节
- 循环终止条件:当
left > right时结束。即使left == right,仍需比较一次以确认目标值是否存在。 - 时间复杂度:O(logN) 相比 O(N) 效率极高。在 int 范围内,O(N) 最多约 4×10^9 次比较,而 O(logN) 仅需 32 次。
- 防止溢出:计算中点时,
(left + right) / 2可能溢出。推荐使用left + (right - left) / 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;
}
};
2. 查找元素的第一个和最后一个位置(LeetCode 34)
核心思路
数组非递减排序,具有二段性。我们需要分别找到左边界和右边界。
查找左端点
当 mid 对应的值小于目标值时,区间 [left, mid] 全部舍弃,更新 left = mid + 1。当 mid 大于等于目标值时,mid 可能是左端点,保留在区间 [left, mid],更新 right = mid。
细节处理:
- 循环条件:使用
left < right。当 时即为最终结果,无需再判断。


