1. LeetCode 704 二分查找
1.2 算法原理
二分算法的满足条件是数组有序,其实并不严谨,实际上是要具有二段性,即通过有一个数能将数组分为两部分,一次比较能筛选掉一部分。
循环结束条件:
left > right,因为每个区间内的数都是未知的,即使最后 left 和 right 相等还是要跟目标值比较一次,来证明一个数是否存在。
时间复杂度:
O(logN) 和 O(N) 的效率差距很大,在 int 范围内,O(N) 最多要比较执行 4*10^9 次,而 O(logN) 最多只要 32 次。
数据溢出问题:
(left + right) / 2:在大多数情况下是安全的,但如果 left 和 right 的和超过了该类型能表示的最大值,直接相加可能会导致整数溢出。 left + (right - left) / 2 可以避免这个问题,利用起始值 + 偏移值可以有效避免两数相加超出范围,结果相同。
至于 left + (right - left + 1) / 2 和 (left + right + 1) / 2 要不要加 1 的问题,在数组数量为奇数时结果相同。不同在于数量为偶数时中间值有两个数,不加 1 和加 1 计算结果一个在左中间值一个在右中间值,并不影响最终结果。
1.3 总结模板
该模板为最朴素的二分查找模板,适用范围一般限制较多,后续会总结左右边界的判断模板,为万能模板,适用范围更广。
1.4 代码
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] < target) left = mid + 1;
else if (nums[mid] > target) right = mid - 1;
else if (nums[mid] == target) return mid;
}
return -1;
}
};
2. LeetCode 34 在排序数组中查找元素的第一个和最后一个位置
非递减顺序排列就是递增序列或不变。


