34. 在排序数组中查找元素的第一个和最后一个位置
描述
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
分析
对比之前的二分搜索,找到对应target就返回结果。这道题的要求更进一步,给定数组中寻找的target可能存在多个,要求找到其左右区间之后再返回。
思路
改进之处:分别寻找左右边界
- 利用二分法寻找左边界:往左区间寻找时(right=mid-1;),若找到了对应的target元素,可以用变量leftBound做个记录,然后跳过该元素继续往左区间寻找;往右区间寻找时,逻辑相同。
- 利用二分法寻找右边界:往右区间寻找时(left=mid+1;),若找到了对应的target元素,可以用变量rightBound做个记录,然后跳过该元素继续往左区间寻找;往左区间寻找时,逻辑相同。
- 最后返回左右边界即可
代码
寻找左边界
public int getLeftBound(int[] nums, int target){
int left=0;
int right=nums.length-1;
int mid;
int leftBound=-1;
while(left<=right){
mid=(left+right)/2;
if(nums[mid]<target){
left=mid+1;
}else{
right=mid-1;
leftBound=mid;
}
}
if(leftBound!=-1&&nums[leftBound]==target){
return leftBound;
}
return -1;
}
寻找右边界
public int getRightBound(int[] nums, int target){
int left=0;
int right=nums.length-1;
int mid;
int rightBound=-1;
while(left<=right){
mid=(left+right)/2;
if(nums[mid]>target){
right=mid-1;
}else{
left=mid+1;
rightBound=mid;
}
}
if(rightBound!=-1&&nums[rightBound]==target){
return rightBound;
}
return -1;
}
最终代码
public int[] searchRange(int[] nums, int target) {
int left=getLeftBound(nums,target);
int right=getRightBound(nums,target);
return new int[]{left,right};
}