给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一反应是二分法:
class Solution {
public int[] searchRange(int[] nums, int target) {
int l = 0 , r = nums.length - 1 ;
while(l <= r){
int mid = (l + r)/2 ;
if(nums[mid] == target){//找到target后,向两边查找
int a=mid,b=mid ;
while(a>= 0 && nums[a] == target){
a-- ;
}
while(b < nums.length && nums[b] == target){
b++ ;
}
return new int [] {a + 1 , b - 1};
}
if(nums[mid]<target){
l = mid + 1 ;
}else{
r = mid - 1 ;
}
}
return new int []{-1,-1};
}
}
这个方法虽然披着二分法的外衣,但实质上,时间复杂度是O(n),因为最差情况,遍历了一遍(全是target)。
别人的解法:
class Solution {
public int search(int [] nums , int target , boolean left){//left控制非常绝妙。左右不同。
int l = 0 , r = nums.length ;
while(l < r){
int mid = (l + r)/2;
if(nums[mid]>target || (left && nums[mid] == target)){
r = mid ;
}else{
l = mid + 1 ;
}
}
return l ;
}
public int[] searchRange(int[] nums, int target) {
int [] ans = {-1,-1};//可以把结果先初始化出来。
int leftans = search(nums,target,true);
if(leftans == nums.length || nums[leftans] != target){//看看有没有找到target
return ans ;
}
ans[0] = leftans ;
ans[1] = search(nums,target,false)-1;
return ans ;
}
}
这是才是二分法。找到target后,没有停止,而是继续找到边界。