首先,循环法实现二分查找的模版给我背过。精髓在于把退出循环的条件放在了while()里。
java
//二分查找法模版,背过!!!
//因为我们拥有整个数组的全局视野,所以用循环就好了,不写递归了
int findTarget(int[] nums, int target){
int left = 0;
int right=nums.length-1;
//退出循环的条件放在while里
while(left<=right){
int mid=(left+right)/2;
if(nums[mid]==target) return mid;
else if(target>nums[mid]) left=mid+1; //不用去做left是否溢出的判断,都在while()里做了
else right=mid-1; //不用做right是否溢出的判断,都在while()里做了
}
return -1; //没有
}

二分查找的变种,但只修改了if(nums[mid]==tartget)这个分支:标准的二分查找命中后,直接return,但是这里我们不return,继续找。
进行两次二分查找,第一次找最大下标,第二次找最小下标。
java
class Solution {
public int[] searchRange(int[] nums, int target) {
//特殊情况
if(nums.length==0) return new int[]{-1,-1};
int targetMaxIndex = findTargetMaxIndex(nums, target);
int targetMinIndex;
if(targetMaxIndex==-1){
return new int[]{-1,-1};
}else{
targetMinIndex = findTargetMinIndex(nums,target);
}
return new int[] {targetMinIndex,targetMaxIndex};
}
private int findTargetMaxIndex(int[] nums,int target){
//进入循环前的初始化
int left=0;
int right=nums.length-1;
int maxIndex=-1;
while(left<=right){
int mid=(left+right)/2;
//如果命中了,不return,假装没找到,继续往右边找更右边的
if(nums[mid]==target) {
maxIndex = Math.max(maxIndex, mid);
left = mid + 1;
//没命中,target在nums[mid]右边,继续往右边找(跟二分查找一样
}else if(target>nums[mid]){
left=mid+1;
//没命中,target在nums[mid]左边,继续往左边找(跟二分查找一样
}else{
right=mid-1;
}
}
if(maxIndex!=-1) return maxIndex;
return -1;
}
private int findTargetMinIndex(int[] nums,int target){
//进入循环前的初始化
int left=0;
int right=nums.length-1;
int minIndex=nums.length;
while(left<=right){
int mid=(left+right)/2;
//如果命中了,不return,假装没找到,继续往左边找更左边的
if(nums[mid]==target){
minIndex=Math.min(minIndex,mid);
right=mid-1;
//(跟二分查找一样
}else if(target>nums[mid]){
left=mid+1;
//(跟二分查找一样
}else{
right=mid-1;
}
}
if(minIndex!=nums.length) return minIndex;
return -1;
}
}