Given an array of integers nums
sorted in ascending order, find the starting and ending position of a given target
value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1]
.
Example 1:
Input: nums = [5,7,7,8,8,10]
, target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10]
, target = 6
Output: [-1,-1]
这道题有两种解法, 第一是写一个demo, 这个demo能找到target在数组当中的最小索引, 然后调用两次demo,传入的参数分别是target 和 target + 1. 即可解决。 第二种解法是变种的二分查找. (另外在写二分查找的时候while循环中lo < hi 还是lo <=hi.取决于hi的定义) 我的习惯hi = nums.length - 1这时候就是lo <= hi, 因为不这样的话当数组只有1个元素的时候他就不会进入while循环, 这个元素就没有被查找。 一般的二分查找这样是没问题的, 但是在这道题当中查不到元素要返回的是-1, 所以你必须进入这个while循环, 这也是一些编程细节的问题。
// 方法1
public int[] searchRange(int[] A, int target) {
int start = Solution.firstGreaterEqual(A, target);
if (start == A.length || A[start] != target) {
return new int[]{-1, -1};
}
return new int[]{start, Solution.firstGreaterEqual(A, target + 1) - 1};
}
//find the first number that is greater than or equal to target.
//could return A.length if target is greater than A[A.length-1].
//actually this is the same as lower_bound in C++ STL.
private static int firstGreaterEqual(int[] A, int target) {
int low = 0, high = A.length;
while (low < high) {
int mid = low + ((high - low) >> 1);
//low <= mid < high
if (A[mid] < target) {
low = mid + 1;
} else {
//should not be mid-1 when A[mid]==target.
//could be mid even if A[mid]>target because mid<high.
high = mid;
}
}
return low;
}
// 方法2
public int[] searchRange(int[] nums, int target) {
int lo = 0;
int[] res = new int[2];
int left = findFirstK(nums, target);
int right = findLastK(nums, target);
res[0] = left;
res[1] = right;
return res;
}
public int findFirstK(int[] nums, int target) {
int lo = 0;
int hi = nums.length - 1;
while( lo <= hi) {
int mid = (lo + hi) / 2;
if(nums[mid] < target){
lo = mid + 1;
} else if(nums[mid ] > target) {
hi = mid - 1;
} else if(mid - 1 >= 0 && nums[mid - 1] == target) {
hi = mid - 1;
} else {
return mid;
}
}
return -1;
}
public int findLastK(int[] nums, int target) {
int lo = 0;
int hi = nums.length - 1;
while( lo <= hi) {
int mid = (lo + hi) / 2;
if(nums[mid] < target){
lo = mid + 1;
} else if(nums[mid ] > target) {
hi = mid - 1;
} else if(mid + 1 < nums.length && nums[mid + 1] == target) {
lo = mid + 1;
} else {
return mid;
}
}
return -1;
}