目录
1. 题目解析
题目链接:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
这道题就是找出目标值在数组中的起始位置和结束位置。
2. 算法原理
这里如果我们直接使用标准的二分去做,如果整个数组都是是同一个数,
就会退化成 O(N),所以这里我们需要对他进行一个优化,
1. 先从查找左端点开始分析:设 x 为 mid 值,t 为目标值
如果 x < t ,left = mid + 1
如果 x >= t ,right = mid(我们这里把大于和等于的情况合并了)
这样设置就在 left == right 的时候就是最终结果,
而我们求中点的方式必须是 left + ( right - left ) / 2(也就是求偶数的形式)
这样每步走会靠近左端点,就不会陷入死循环。
2. 我们再来分析查找右端点:
如果 x <= t ,left = mid(为什么这里不用 + 1,因为如果刚好落在目标值上,不久越过了吗)
如果 x > t ,right = mid - 1
这样当 left == right 的时候也就是最终结果了,
而我们求中点的方式就得是 left + ( right - left + 1 ) / 2
这样每步走会靠近右端点,就不会陷入死循环。
3. 代码编写
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.size() == 0) return {-1, -1}; // 处理越界
int left = 0, right = nums.size() - 1, begin = 0;
while(left < right) {
int mid = left + (right - left) / 2;
if(nums[mid] < target) left = mid + 1;
else right = mid;
}
if(nums[left] != target) return {-1, -1};
else begin = left;
left = 0, right = nums.size() - 1;
while(left < right) {
int mid = left + (right - left + 1) / 2;
if(nums[mid] <= target) left = mid;
else right = mid - 1;
}
return {begin, right};
}
};
4. 二分的模板
查找左端点的时候:
while(left < right) {
int mid = left + (right - left) / 2;
if(...) left = mid + 1;
else right = mid;
}
while (left < right) {
int mid = left + (right - left) / 2;
if (...) left = mid + 1;
else right = mid;
}
查找右端点的时候:
while(left < right) {
int mid = left + (right - left + 1) / 2;
if(...) left = mid;
else right = mid - 1;
}
while (left < right) {
int mid = left + (right - left + 1) / 2;
if (...) left = mid;
else right = mid - 1;
}
写在最后:
以上就是本篇文章的内容了,感谢你的阅读。
如果感到有所收获的话可以给博主点一个赞哦。
如果文章内容有遗漏或者错误的地方欢迎私信博主或者在评论区指出~