给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8 输出: [3,4] 示例 2:
输入: nums = [5,7,7,8,8,10], target = 6 输出: [-1,-1]
/**
* 如果只是找到一个,那么直接用二分查找即可
* 要找到最左边和最右边符合条件的,那么需要在找到符合条件的之后,再分别往左或者往右找
* 使用递归往左/右找的时候,有可能在上一次递归找到了,在下一次递归没有找到,因此需要在递归的时候记录一下上次找到的位置
* */
public static int[] searchRange(int[] nums, int target) {
int pos = searchLeft(nums, 0, nums.length - 1, target);
int rightPos = searchRight(nums, 0, nums.length - 1, target);
if (pos == -1 || rightPos == -1) {
return new int[]{-1, -1};
}
return new int[]{pos, rightPos};
}
public static int searchLeft(int[] nums, int left, int right, int target) {
//二分查找
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
//找到之后继续往左找
int leftPos = searchLeft(nums, left, mid - 1, target);
//如果递归返回-1,那么本次返回找到的mid
if (leftPos == -1) {
return mid;
}
//否则返回leftPos
return leftPos;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
public static int searchRight(int[] nums, int left, int right, int target) {
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
int rightPos = searchRight(nums, mid + 1, right, target);
if (rightPos == -1) {
return mid;
}
return rightPos;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}