Given a sorted array of integers, 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).
这道题让寻找一个搜索范围,基本思路还是和二分搜索的模型一样,直接上代码,再逐块解析
public int[] searchRange(int[] A, int target) {
int[] result = new int[2];
result[0] = -1;
result[1] = -1;
if (A == null || A.length == 0)
return result;
int left = 0;
int right = A.length - 1;
int middle = 0;
while (left <= right) {
middle = (left + right) / 2;
if (A[middle] == target) {
result[0] = middle;
result[1] = middle;
break;
}
if (A[middle] < target)
left = middle + 1;
else
right = middle - 1;
}
if (A[middle] != target)
return result;
int newLeft = 0;
int newRight = middle - 1;
while (newLeft <= newRight) {
int newMiddle = (newLeft + newRight) / 2;
if (A[newMiddle] == target)
newRight = newMiddle - 1;
else
newLeft = newMiddle + 1;
}
result[0] = newLeft;
newLeft = middle + 1;
newRight = A.length - 1;
while (newLeft <= newRight) {
int newMiddle = (newLeft + newRight) / 2;
if (A[newMiddle] == target)
newLeft = newMiddle + 1;
else
newRight = newMiddle - 1;
}
result[1] = newRight;
return result;
}
首先第一步是和二分搜索的思路完全一样,直接找一个可行解,如果没找到,返回【-1,-1】。
int left = 0;
int right = A.length - 1;
int middle = 0;
while (left <= right) {
middle = (left + right) / 2;
if (A[middle] == target) {
result[0] = middle;
result[1] = middle;
break;
}
if (A[middle] < target)
left = middle + 1;
else
right = middle - 1;
}
if (A[middle] != target)
return result;
然后扩展左界,思路是让左指针指向最左边的一个满足目标值的位置,范围是从0~middle-1
如果A[newMiddle]==target, 收敛右指针
否则收敛左指针。
int newLeft = 0;
int newRight = middle - 1;
while (newLeft <= newRight) {
int newMiddle = (newLeft + newRight) / 2;
if (A[newMiddle] == target)
newRight = newMiddle - 1;
else
newLeft = newMiddle + 1;
}
result[0] = newLeft;
最后扩展右界,思路是让右指针指向最右边的一个满足目标值的位置,范围是从middle+1~A.length-1
如果A[newMiddle]==target, 收敛左指针
否则收敛右指针。
newLeft = middle + 1;
newRight = A.length - 1;
while (newLeft <= newRight) {
int newMiddle = (newLeft + newRight) / 2;
if (A[newMiddle] == target)
newLeft = newMiddle + 1;
else
newRight = newMiddle - 1;
}
result[1] = newRight;
return result;
}
这道题用循环,代码比较多,如果用递归,代码会简单很多
public int[] searchRange(int[] A, int target) {
int[] result = new int[2];
result[0] = -1;
result[1] = -1;
if (A == null || A.length == 0)
return result;
int index = binarySearch(A, 0, A.length - 1, target);
if (index != -1) {
int left = index;
int right = index;
result[0] = left;
result[1] = right;
while ((left = binarySearch(A, 0, left - 1, target)) != -1)
result[0] = left;
while ((right = binarySearch(A, right + 1, A.length - 1, target)) != -1)
result[1] = right;
}
return result;
}
public int binarySearch(int[] A, int left, int right, int target) {
if (left > right)
return -1;
int middle = (left + right) / 2;
if (A[middle] == target)
return middle;
if (A[middle] > target)
return binarySearch(A, left, middle - 1, target);
else
return binarySearch(A, middle + 1, right, target);
}
还有一种更牛的解法是寻找目标值的-0.5和+0.5.然后a指向-0.5, b指向0.5,然后返回【a, b-1】就可以了
比如[5,7,7,8,8,10] 如果要找8,直接搜7.5和8.5 这样能找到3和5,然后返回3和4就可以了
代码如下
public int[] searchRange(int[] A, int target) {
int[] result = new int[2];
result[0] = -1;
result[1] = -1;
if (A == null || A.length == 0)
return result;
double T1 = target - 0.5;
double T2 = target + 0.5;
result[0] = binarySearch(A, 0, A.length - 1, T1);
result[1] = binarySearch(A, 0, A.length - 1, T2) - 1;
if (result[0] > result[1]) {
int[] err = { -1, -1 };
return err;
}
return result;
}
public int binarySearch(int[] A, int left, int right, double target) {
if (left > right)
return left;
int middle = (left + right) / 2;
if (A[middle] > target)
return binarySearch(A, left, middle - 1, target);
else
return binarySearch(A, middle + 1, right, target);
}