LeetCode HOT 100:在排序数组中查找元素的第一个和最后一个位置
题目:34. 在排序数组中查找元素的第一个和最后一个位置
题目描述:
给你一个递增数组,和一个目标值target
,最终返回数组中第一次出现target
和最后一次出现target
的下标。如果该数组中没有target
,返回[-1, -1]
。如果只出现了一次target
,返回的第一次和最后一次出现的下标相同。
思路:
这一题要求第一次出现target
和最后一次出现target
的下标。因为数组是递增的,如果能求得小于target
的最大值的下标,设为start
,那么start + 1
下标对应的值就应该是第一次出现target
的下标。然后,再用同样的方法,求得小于target + 1
的最大值的下标,设为end
,这个end
下标就是target
最后一次出现的下标,最终返回[start + 1, end]
。
举个例子:数组[100, 300, 300, 500, 500, 800, 1000]
,target
为500
,那么start
就应该是小于target
的最大值的下标2
,小于target + 1
的最大值的下标end
应该是4
,所以最终返回[3, 4]
。
步骤:
1、先找到小于target
的最大值的下标,设为start
,使用二分可以实现
2、判断start + 1
下标,如果等于数组长度或者start + 1
下标对应的值不为target
,说明数组中根本没有出现过target
,直接返回[-1, -1]
3、找到小于target + 1
的最大值的下标,设为end
,同样二分实现
4、返回[start + 1, end]
代码:
public int[] searchRange(int[] nums, int target) {
if (nums == null || nums.length == 0) return new int[]{-1, -1};
// lessMostRight得到小于target的最大值下标,如果nums中有target,该下标的下一个(+1)应该就是target的下标
int start = lessMostRight(nums, target, 0, nums.length - 1) + 1;
// 如果数组越界了,或者下一个下标并不是target,说明数组中没有target元素
if (start == nums.length || nums[start] != target) return new int[]{-1, -1};
// 得到小于 target + 1 的最大值下标,就是target的最右边下标
int end = lessMostRight(nums, target + 1, start, nums.length - 1);
return new int[]{start, end};
}
// 找到nums数组中,小于target的最右边的值的下标(因为数组不递减,也就是得到小于target的最大值下标)
public int lessMostRight(int[] nums, int target, int start, int end) {
int mid = 0;
int ans = -1;
while (start <= end) {
mid = start + ((end - start) >> 1);
if (nums[mid] < target) {
start = mid + 1;
ans = mid;
} else {
end = mid - 1;
}
}
return ans;
}