问题:
思路:
这里的二分查找,不同于之前的那个,这里边元素可以重复
第一步:先用二分法找到target;
第二步:从mid分成两部分,分别找第一个元素和最后一个
第一步,就不用多说,详情可以参考我之前的一篇笔记LeetCode第704题,二分查找,Java实现_代码小船的博客-CSDN博客
第一步是 step1和step2;然后以mid为分界线,将数组划分为两部分,left-mid 和 mid-right;
这里只讨论第二步:第二步如果用线性查找的方法,就不满足时间复杂度了,需要继续使用二分查找法,先讨论前半段,也就是找到第一个target,
这个时候主要目标就是 找到最后一个 <target 的数,最后不满足条件的right1+1记为答案
同理:后半段,找到第一个 >target 的数,最后的left-1即为答案;
5 | 7 | 7 | 8 | 8 | 10 | ||
step1 | left | mid | right | ||||
step2 | left | mid | right | ||||
step3 | left1, right1, mid1 | left2, right2 mid1 | |||||
step4 | right1 | legt1 | right2 | left2 | |||
代码:
class Solution {
public int[] searchRange(int[] nums, int target) {
int left = 0;
int right = nums.length-1;
int[] result = new int[2];
while(left <= right){
int mid = left + (right-left)/2;
if(nums[mid] > target){
right = mid-1;
}else if(nums[mid] == target){
result[0] = searchFirst(nums, left, mid-1,target);//前半段
result[1] = searchLast(nums, mid+1, right,target);//后半段
return result;
}else if(nums[mid] < target){
left = mid+1;
}
}
result[0] = -1;
result[1] = -1;
return result;
}
public int searchFirst(int nums[],int left,int right, int target){
while(left<=right){
int mid = left + (right-left)/2;
if(nums[mid] >= target){
right = mid-1;
}else{
left = mid+1;
}
}
return right+1;
}
public int searchLast(int nums[], int left, int right,int target ){
while(left<=right){
int mid = left + (right-left)/2;
if(nums[mid] <= target){
left = mid + 1;
}else{
right = mid - 1;
}
}
return left-1;
}
}