问题
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
思路
基本思路是用二分查找。当找第一个时,如果nums[mid]恰好为target,需要判断mid的左边的数字是否是target,如果是可以往左找;否则直接返回。找最后一个时,同理可得。
代码
class Solution {
public int[] searchRange(int[] nums, int target) {
int low = findLowIndex(nums, target);
int high = findHighIndex(nums, target);
return new int[] {low, high};
}
private int findLowIndex(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int low = 0;
int high = nums.length - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (nums[mid] == target) {
// mid-1后不要超过low
if (mid - 1 >= low && nums[mid - 1] == target ) {
high = mid - 1;
} else {
return mid;
}
}
if (nums[mid] > target) {
high = mid - 1;
}
if (nums[mid] < target) {
low = mid + 1;
}
}
return -1;
}
private int findHighIndex(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int low = 0;
int high = nums.length - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (nums[mid] == target) {
if (mid + 1 <= high && nums[mid + 1] == target) {
low = mid + 1;
} else {
return mid;
}
}
if (nums[mid] > target) {
high = mid - 1;
}
if (nums[mid] < target) {
low = mid + 1;
}
}
return -1;
}
}
代码二
public class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = {-1, -1};
int start = 0;
int end = nums.length - 1;
int mid = 0;
while (start <= end) {
mid = start + ((end - start) >>> 1);
//target < nums[mid]肯定往左找
//找下确界,即使相等也要往左找
if (target <= nums[mid]) {
end = mid - 1;
} else {
//target >= nums[mid]
start = mid + 1;
}
}
if (start < nums.length && nums[start] == target) {
result[0] = start;
end = nums.length - 1;
while (start <= end) {
mid = start + ((end - start) >>> 1);
if (target < nums[mid]) {
end = mid - 1;
} else {
start = mid + 1;
}
}
result[1] = end;
return result;
}
return result;
}
}
官方
官方给的思路:相当于查找第一个大于等于target的下标,和第一个大于target的下标-1。
如果查找第一个大于等于target的下标,只需要在原有二分法中,当大于等于就往左走。
class Solution {
public int[] searchRange(int[] nums, int target) {
int left = binarySearch(nums, target, true);
int right = binarySearch(nums, target, false) - 1;
if (left <= right && nums[left] == target && nums[right] >= target) {
return new int[] {left, right};
}
return new int[] {-1, -1};
}
// 第一个大于target或者第一个大于等于target的下标
private int binarySearch(int[] nums, int target, boolean left) {
int low = 0, high = nums.length - 1, res = nums.length;
while (low <= high) {
int mid = (low + high) / 2;
if (nums[mid] > target || (left && nums[mid] >= target)) {
high = mid - 1;
res = mid;
} else {
low = mid + 1;
}
}
return res;
}
}
复杂度
时间复杂度:O(logn) 空间复杂度:O(1)
硬广告
欢迎关注公众号:double6