数组满足单调的特点,考虑用二分法分别求解目标值的开始位置和结束位置。
情况1: nums=[5,7,7,8,8,10],target=8,返回[3,4]
情况2: nums=[5,7,7,8,8,10],target=6,返回[-1,-1]
情况3: nums=[],target=0,返回[-1,-1]
设置一个low指针和high指针,分别指向数组起始和最后一个位置。令mid指针指向low指针和high指针指向数组的中间位置。对于目标值在数组中的开始位置和结束位置,并不包括目标值。比如在以上例子中,我们要找target=8,我们找到的开始位置为2,结束位置为5。
寻找开始位置:
开始位置的数值一定比目标值小。因此在nums[mid]>=target的时候,我们都让high=mid-1,那么high指针指向的位置最终将恰好比目标值小。
int getStart(int[] nums,int target){
int low=0;
int high=nums.length-1;
int mid;
int start=-2;//赋值为-2避免了与nums的第一个元素是target时产生冲突的情况,当nums=[],不执行循环体,直接return -2.
while(low<=high){
mid =(low+high)/2;
if(nums[mid]<target){
low=mid+1;
}
else if(nums[mid]>=target){
high=mid-1;
start=high;
}
}
return start;
}
寻找结束位置:
结束位置的指针指向的元素一定比target大,因此在nums[mid]<=target的时候,令low=mid+1,那么low指针最终指向的位置一定比target恰好大
int getEnd(int[] nums,int target){
int low=0;
int high=nums.length-1;
int mid;
int end=-2;
while(low<=high){
mid=(low+high)/2;
if(nums[mid]<=target){
low=mid+1;
end=low;
}
else if(nums[mid]>target){
high=mid-1;
}
}
return low;
}
最终的代码如下:
class Solution {
public int[] searchRange(int[] nums, int target) {
int start=getStart(nums,target);
int end=getEnd(nums,target);
if(nums.length==0){
return new int[] {-1, -1};
}
else if(end-start<=1){
return new int[] {-1, -1};
}
else{
return new int[]{start+1, end-1};
}
}
int getStart(int[] nums,int target){
int low=0;
int high=nums.length-1;
int mid;
int start=-2;
while(low<=high){
mid =(low+high)/2;
if(nums[mid]<target){
low=mid+1;
}
else if(nums[mid]>=target){
high=mid-1;
start=high;
}
}
return start;
}
int getEnd(int[] nums,int target){
int low=0;
int high=nums.length-1;
int mid;
int end=-2;
while(low<=high){
mid=(low+high)/2;
if(nums[mid]<=target){
low=mid+1;
end=low;
}
else if(nums[mid]>target){
high=mid-1;
}
}
return low;
}
}
--------2023.12.21---------
发现以上程序在输入为nums=[2,2],target=3时start指针没有被赋值,为初始值-2,但是low指针会指向2,导致最终结果为[-1,1],出错。在nums中没有包含target时将会出错。我们纠正程序,确保程序能够发现数组中的target,发现不了就返回-1.
class Solution {
public int[] searchRange(int[] nums, int target) {
int start=getStart(nums,target);
int end=getEnd(nums,target);
if(nums.length==0){
return new int[] {-1, -1};
}
else{
return new int[]{start, end};
}
}
int getStart(int[] nums,int target){
int low=0;
int high=nums.length-1;
int mid;
int start=-1;
while(low<=high){
mid =(low+high)/2;
if(nums[mid]==target){
start=mid;
high=mid-1;
}
else if(nums[mid]>target){
high=mid-1;
}else{
low=mid+1;
}
}
return start;
}
int getEnd(int[] nums,int target){
int low=0;
int high=nums.length-1;
int mid;
int end=-1;
while(low<=high){
mid=(low+high)/2;
if(nums[mid]==target){
end=mid;
low=mid+1;
}
else if(nums[mid]<target){
low=mid+1;
}else{
high=mid-1;
}
}
return end;
}
}