重点
本题直接容易想到的方法为从头到尾的遍历,查找符合目标的结果,但是这种方法时间复杂度为O(n),不满足时间复杂度的要求。由于给定的序列为已经排列好的升序序列,容易想到采用二分法进行查找。
主要步骤:
1.使用正常的而二分查找,查找到一个目标值
2.以目标值为基准点,分别向左,向右使用二分查找查找起始点和结束点。以查找起始点为例,当nums[leftMid]<target时,则left=leftMid+1。如果nums[leftMid]=target,则mid=leftMId,避免出现漏掉端点。结束点查找同理。
需要处理的意外情况:
1.target位于数组开头,将0赋给返回数组1,只需要查找结束点。
2.target位于数组结束,将n-1赋给ret[1],只需要查找起始点。
代码
代码如下(示例):
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] ret= new int[]{-1,-1};
int n=nums.length;
if(n==0){
return ret;
}//初始化,若nums为空则返回-1,-1;
int left=0,right=n-1,mid=0;
while (left<=right){ /正常查找
mid=left+(right-left)/2;
if (nums[mid]>target){
right=mid-1;
}
if (nums[mid]<target){
left=mid+1;
}
if (nums[mid]==target){
break;
}
}
if (nums[mid]!=target) return ret;
if (mid==0) ret[0]=mid;
if (mid==n-1)ret[1]=mid; //处理额外情况
while (left!=mid){
int targetLeft=left+(mid-left)/2;
if(nums[targetLeft]<target) left=targetLeft+1;
if (nums[targetLeft]==target) mid=targetLeft;
}
ret[0]=mid;
while (right!=mid){
int targetRight=right+(mid-left)/2;
if(nums[targetRight]>target) right=targetRight-1;
if (nums[targetRight]==target) mid=targetRight;
}
ret[1]=right;
return ret;
}
}