34. 在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
题例
示例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]
分析
题目给的整数数组是一个升序排列的数组,排序数组查找元素,我们采用二分查找法进行查找。通过不断的缩小区间,最后定位到该元素可能存在的区间,再判断其是否存在,返回我们的结果。
实现
class Solution {
public int[] searchRange(int[] nums, int target) {
if(nums.length==0) return new int[]{-1,-1};
int left = searchLeft(0,nums.length-1,nums,target);
int right = searchRight(0,nums.length-1,nums,target);
return new int[]{left,right};
}
private int searchLeft(int left,int right,int[] nums,int target){
while(left<right){
int mid = (left+right)>>>1;
if(nums[mid]<target) left=mid+1;
else right = mid;
}
return nums[left]==target?left:-1;
}
private int searchRight(int left,int right,int[] nums,int target){
while(left<right){
int mid = (left+right+1)>>>1;
if(nums[mid]>target) right = mid-1;
else left = mid;
}
return nums[left]==target?left:-1;
}
}
说明
首先判断数组是否为空,如果是空数组就直接返回[-1,-1]了
if(nums.length==0) return new int[]{-1,-1};
题目的要求是返回目标值在数组中的开始位置和结束位置,我们分开做处理。 左边的采用下取整,逐渐缩小左边的区间范围。
private int searchLeft(int left,int right,int[] nums,int target){
while(left<right){
int mid = (left+right)>>>1;
if(nums[mid]<target) left=mid+1;
else right = mid;
}
return nums[left]==target?left:-1;
}
右边的采用上取值,逐渐缩小右边的区间范围。
private int searchRight(int left,int right,int[] nums,int target){
while(left<right){
int mid = (left+right+1)>>>1;
if(nums[mid]>target) right = mid-1;
else left = mid;
}
return nums[left]==target?left:-1;
}
上取值和下取整的不同之处就在于这两段代码。
int mid = (left+right)>>>1;
int mid = (left+right+1)>>>1;
>>>1和>>1的区别以及上取值和下取整的使用在二分查找中也有讲过,有兴趣的朋友可以去看一看。
Comments | NOTHING