一个升序数组,找出与target相等的元素的位置,会有两个。
For example,
Given [5, 7, 7, 8, 8, 10]
and target value 8,
return [3, 4]
.
如果找不到就返回[-1, -1].时间复杂度要求O(logn)
class Solution {
public int[] searchRange(int[] nums, int target) {
int start = 0, end = nums.length - 1, idx = -1;
int mid = (start + end) / 2;
int result[] = new int[2];
while (start <= end) {
if (nums[mid] < target) start = mid + 1;
else end = mid - 1;
if(nums[mid] == target) idx = mid;
}
result[0] = idx;
start = idx;
end = nums.length - 1;
idx = -1;
while (start <= end){
mid = (start + end + 1) / 2; //让mid向右边界靠近Make mid biased to the right
if (nums[mid] > target) end = mid - 1;
else start= mid;
if(nums[mid] == target) idx = mid;
}
result[1] = idx;
return result;
}
}
这个还超复杂度我也是醉了...这第二次二分的时候start从第一个target的index处开始还超,不懂啊!只能看别人的思路了,java的全都是调用函数的,看了这个感觉比较好理解:
public class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = new int[2];
result[0] = findFirst(nums, target);
result[1] = findLast(nums, target);
return result;
}
private int findFirst(int[] nums, int target){
int idx = -1;
int start = 0;
int end = nums.length - 1;
while(start <= end){
int mid = (start + end) / 2;
if(nums[mid] >= target){//向左边界靠近
end = mid - 1;
}else{
start = mid + 1;
}
if(nums[mid] == target) idx = mid;
}
return idx;
}
private int findLast(int[] nums, int target){
int idx = -1;
int start = 0;
int end = nums.length - 1;
while(start <= end){
int mid = (start + end) / 2;
if(nums[mid] <= target){//向右边界靠近
start = mid + 1;
}else{
end = mid - 1;
}
if(nums[mid] == target) idx = mid;
}
return idx;
}
}
这个思路比较复杂一点,但用的很巧妙
class Solution {
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}; //如果不要A.length == start会超出数组范围,因为如果target大于数组里最大数则start会到A.length的地方从而超出了A[]的范围。后一个表示如果target小于最小数时的情况
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.
//如果target在数组中,返回的一定是target的第一个值,因为如果是第二个不会结束循环,而会将high赋给mid(此时start一定小于mid,因为前面至少还有一个target)所以会再次循环从而找到第一个target(其实就是因为A[mid] < target这里没有=号,说明是向左边界靠近的)
private static int firstGreaterEqual(int[] A, int target) {
int low = 0, high = A.length;
while (low < high) {
int mid = (low + high) / 2;
//low <= mid < high
if (A[mid] < target) low = mid + 1;
else high = mid;
//should not be mid-1 when A[mid]==target.
//could be mid even if A[mid]>target because mid<high.
}
return low;
}
}
总结:这两种方法都没有在第二次的时候从第一个target的索引开始,其实是比较复杂的,不如C++