题目链接
思路:
- 一个自然的想法是先二分查找然后分别往左右遍历,找到所求的位置。但这样的话,最优复杂度达不到进阶题目要求的情况。或许可以在面试的时候先这么说,引导面试官让你优化,然后惊艳面试官,哈哈哈~
- 使用两次二分查找,分别查找满足要求的左右坐标值,具体的思路在代码注释中了。
网上一个优秀题解的情况分析:
AC代码:
class Solution {
public:
int searchleft(vector<int> &nums, int target){
//第一个小于target的数的坐标
//不断取左半区间 然后返回右边界值
//为什么res指示值为-2?
//因为在返回右边界的情况下是mid-1,可能取值为-1,因此res指示值不能取-1了
int left = 0, right = nums.size() - 1, res = -2;
while(left<=right){
int mid = (left + right) / 2;
// 注意细节 大于等于号 然后坐标减一
//如果res的值不再更新 也就是不再进入到这个判断条件中
//那么res坐标的值必然是小于target值的第一个坐标
if(nums[mid]>=target){
right = mid - 1;
res = right;
}
else{
left = mid + 1;
}
}
return res; // res为-2说明数组中所有元素均小于target
}
int searchright(vector<int> & nums, int target){
//第一个大于target的数的坐标
//不断取右半区间,返回左边界
int left = 0, right = nums.size() - 1, res = -2;
while(left<=right){
int mid = (left + right) / 2;
if(nums[mid]<=target){
left = mid + 1;
res = left;
}
else{
right = mid - 1;
}
}
return res; //res为-2则代表所有元素均小于target
}
vector<int> searchRange(vector<int>& nums, int target) {
int leftidx = searchleft(nums, target);
int rightidx = searchright(nums, target);
if(leftidx == -2 || rightidx == -2) return {-1, -1}; // 情况1
// target的值在区间中
if(rightidx - leftidx > 1){ // 确保至少存在一个target值
return {leftidx + 1, rightidx - 1}; // 情况3
}
else return {-1, -1}; // 情况2
}
};