一、题目
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
二、解法
二分查找:
寻找leftIdx(第一个大于等于target的下标)和rightIdx(第一个严格大于target的下标),即可得到{leftIdx,rightIdx-1}
需要注意的地方:
- 由于要用到两次二分查找,抽象出一个函数
//larger:true:严格大于,false:大于等于
int firstIndex(vector<int>& nums,int target,bool larger);
- 得到下标后需要进行判断,leftIdx是第一个大于等于target的下标,很可能没找到,所以要判断nums[leftIdx]==target
- rightIdx是第一个大于target的下标,如果数组以target结尾,则rightIdx=-1找不到,此时rightIdx应该改为nums.size()-1
class Solution {
public:
int firstIndex(vector<int>& nums,int target,bool larger){ //larger:true:严格大于,false:大于等于
int n=nums.size();
int l=0,r=n-1,mid;
int ans=-1;
while(l<=r){
mid=l+(r-l)/2;
if((larger&&nums[mid]>target)||(!larger&&nums[mid]>=target)){
ans=mid;
r=mid-1;
}else{
l=mid+1;
}
}
return ans;
}
vector<int> searchRange(vector<int>& nums, int target) {
int n=nums.size();
int leftIdx=firstIndex(nums,target,false);
int rightIdx=firstIndex(nums,target,true);
if(leftIdx!=-1&&nums[leftIdx]==target){
if(rightIdx!=-1) return {leftIdx,rightIdx-1};
else return {leftIdx,n-1};
}else return {-1,-1};
}
};