题目描述:
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]
解题思路:
使用二分法来做,对于二分法有一句这样的理解:思路很简单,细节是魔鬼。最常用的二分查找场景分别为:寻找一个数、寻找左侧边界、寻找右侧边界。这个题恰好就寻找左侧和右侧边界。leftSearch(int[] nums, int target)用于判断左侧边界是否符合要求;rightSearch(int[] nums, int target)用于判断右侧边界是否符合要求,因为此时left=mid+1,所以最后返回时需要将left-1之后再返回,否则不符合要求。分别求出左侧和右侧的边界,leftSearch(nums, target) == nums.length || leftSearch(nums, target) > rightSearch(nums, target),如果左侧都等于数组的长度了,那么右侧肯定也就不符合要求了,或者是如果左侧边界大于右侧边界时,那肯定也是不符合要求,则直接返回{-1,-1}即可,经过判断之后的返回情况则为符合要求的情况。
执行用时 :1 ms, 在所有 Java 提交中击败了97.94%的用户
内存消耗 :42.2 MB, 在所有 Java 提交中击败了74.75%的用户
代码:
import java.util.Arrays;
public class leetcode_34 {
public static void main(String[] args) {
int[] arr = {5, 7, 7, 8, 8, 10};
System.out.println(Arrays.toString(searchRange(arr, 6)));
}
public static int[] searchRange(int[] nums, int target) {
if (nums.length == 0) {
return new int[]{-1, -1};
}
if (leftSearch(nums, target) == nums.length || leftSearch(nums, target) > rightSearch(nums, target)) {
return new int[]{-1, -1};
}
return new int[]{leftSearch(nums, target), rightSearch(nums, target)};
}
public static int leftSearch(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right) {
int mid = (left + right) / 2;
if (target == nums[mid]) {
right = mid;
} else if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid;
}
}
return left;
}
public static int rightSearch(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right) {
int mid = (left + right) / 2;
if (target == nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid;
} else if (target > nums[mid]) {
left = mid + 1;
}
}
return left - 1;
}
}