题目描述
在排序数组中找到某个元素起始结束的位置 要求logn
一刷 折半 找到pos后前后寻找
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.size()==0) return {-1,-1};
int pos;
bool symbol = false;
int left=0;
int right = nums.size()-1;
//int mid = (left+right)/2;
while(left<=right){
int mid = (left+right)/2;
if(nums[mid]==target){
pos = mid;
symbol = true;
break;
}
else if(nums[mid]<target){
left = mid+1;
}
else{
right = mid-1;
}
}
if(symbol ==true){
int leftpos=pos;
int rightpos=pos;
while(leftpos>0&&nums[leftpos-1]==target){
leftpos--;
}
while(rightpos<nums.size()-1&&nums[rightpos+1]==target){
rightpos++;
}
return {leftpos,rightpos};
}
else{
return {-1,-1};
}
}
};
总结
有个非常好的写法,直接用同一种算法找左右边界
避免找到单个边界后再来进行左右遍历,如果数据段过于长,那么会接近On
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
return {searchLeftOrRightBound(nums, target, "left"), searchLeftOrRightBound(nums, target, "right")};
}
private:
int searchLeftOrRightBound(vector<int>& nums, int target, const string& bound) {
int left = 0, right = nums.size() - 1;
int res = -1;
while (left <= right) {
int mid = (left + right) >> 1;
if (nums[mid] < target) {
left = mid + 1;
}
else if (nums[mid] > target) {
right = mid - 1;
}
else {
res = mid;
if (bound == "left") {
right = mid - 1;
}
else if (bound == "right") {
left = mid + 1;
}
else {
// 异常处理段
}
}
}
return res;
}
};