题目
解析(查找问题用二分法yyds)
由于数组已经排序,因此整个数组是单调递增的,我们可以利用二分法来加速查找的过程。
考虑 target 开始和结束位置,其实我们要找的就是数组中第一个>=target 的位置(记为 leftIdx)和第一个>target 的位置减一(记为rightIdx),如nums = [5,7,7,8,8,10],target = 8,下标leftIdx=3,rightIdx=5-1=4。为了代码的复用,我们定义 binarySearch(nums, target, flag),flag=true表示>=target,flag=false表示>target,最后需要检验leftIdx和rightIdx,因为查找时可能会导致下标值不属于数组下标[0,nums.length-1]这个范围
class Solution {
public int[] searchRange(int[] nums, int target) {
//判空
if(nums == null || nums.length == 0){
return new int[]{-1,-1};
}
//二分查找
int leftIdx = binarySearch(nums,target,true);//>=
int rightIdx = binarySearch(nums,target,false) - 1;//>
//leftIdx肯定>=0,因为left > right跳出,mid最小=0,res=mid,而leftIdx会得到res,所以肯定也>=0
//同理rightIdx也肯定<=nums.length - 1,因为返回的res最大才nums.length
//这里为什么要做检查?leftIdx <= rightIdx 是保证不索引越界,开始位置肯定要<=结束位置
//而做nums[leftIdx] == target && nums[rightIdx] == target因为[1,2,5],target=4情况
//最后res返回1,也就是nums[1]=2,但是2!=4,元素根本不存在
if(leftIdx <= rightIdx && nums[leftIdx] == target && nums[rightIdx] == target){
return new int[]{leftIdx,rightIdx};
}
return new int[]{-1,-1};
}
private int binarySearch(int[] nums, int target, boolean flag){
int left = 0,right = nums.length - 1,res = nums.length;
while(left <= right){
int mid = (left + right) / 2;
// >=和>两种情况合并
if((flag && nums[mid] >= target) || nums[mid] > target){
right = mid - 1;//target在mid左边,要变小
res = mid;//这句自己用题目示例按代码写一遍即可知道,很重要
}else{
left = mid + 1;//target在mid右边,要变大
}
}
return res;
}
}