二分算法实战:查找元素首尾位置及区间计数
二分算法简介
当问题的解具有二段性时,通常可以使用二分算法来寻找答案。核心思路是根据待查找区间的中点位置,分析答案会出现在哪一侧,然后舍弃一半的区间,继续在有效区间内查找。
- 时间复杂度:O(logN)
- STL 辅助函数:
lower_bound:返回大于等于 x 的最小元素的迭代器。upper_bound:返回大于 x 的最小元素的迭代器。
注意:使用 STL 函数时需注意其返回值类型及边界情况,手写二分模板能更好地应对复杂变种。
实战案例一:在排序数组中查找元素的第一个和最后一个位置
题目描述
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值,返回 [-1, -1]。
解题思路
这道题是典型的二分查找变体。我们需要分别找到目标值的左边界和右边界。
- 查找左端点:寻找第一个大于等于
target的位置。若该位置的值不等于target,说明不存在。 - 查找右端点:寻找最后一个小于等于
target的位置。 - 细节处理:
- 区间缩小条件:
left < right。 - 中点计算:查找右边界时,
mid = (left + right + 1) / 2防止死循环。 - 合法性校验:二分结束后必须检查指针指向的值是否确实为目标值。
- 区间缩小条件:
代码实现
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if (nums.empty()) return {-1, -1};
// 1. 二分查找左端点(第一个 >= target 的位置)
int left = 0, right = nums.size() - 1;
while (left < right) {
int mid = (left + right) / ;
(nums[mid] >= target) right = mid;
left = mid + ;
}
(nums[left] != target) {, };
retLeft = left;
left = ; right = nums.() - ;
(left < right) {
mid = (left + right + ) / ;
(nums[mid] <= target) left = mid;
right = mid - ;
}
{retLeft, right};
}
};


