【题目】
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).
If the target is not found in the array, return [-1, -1]
.
For example,
Given [5, 7, 7, 8, 8, 10]
and target value 8,
return [3, 4]
.
【题意】
给定一个排好序的序列,和一个数字,求这个序列等于给定数字的位置范围。
【分析】
二分查找,分别求等于给定数字最靠左的位置和最靠右的位置。
1. 先找左边界。当mid == target,将right移动到mid,继续查找左边界。
最后如果没有找到target,退出
2. 再找右边界。 当mid == target,将left移动到mid,继续查找右边界。
最后如果没有找到target,退出
终止条件是:left < right - 1 这样结束的时候,会有2个值供我们判断。这样做的最大的好处是,不用处理各种越界问题。
【实现】
1 public class Solution {
2 public int[] searchRange(int[] A, int target) {
3 int[] ret = {-1, -1};
4
5 if (A == null || A.length == 0) {
6 return ret;
7 }
8
9 int len = A.length;
10 int left = 0;
11 int right = len - 1;
12
13 // so when loop end, there will be 2 elements in the array.
14 // search the left bound.
15 while (left < right - 1) {
16 int mid = left + (right - left) / 2;
17 if (target == A[mid]) {
18 // 如果相等,继续往左寻找边界
19 right = mid;
20 } else if (target > A[mid]) {
21 // move right;
22 left = mid;
23 } else {
24 right = mid;
25 }
26 }
27
28 if (A[left] == target) {
29 ret[0] = left;
30 } else if (A[right] == target) {
31 ret[0] = right;
32 } else {
33 return ret;
34 }
35
36 left = 0;
37 right = len - 1;
38 // so when loop end, there will be 2 elements in the array.
39 // search the right bound.
40 while (left < right - 1) {
41 int mid = left + (right - left) / 2;
42 if (target == A[mid]) {
43 // 如果相等,继续往右寻找右边界
44 left = mid;
45 } else if (target > A[mid]) {
46 // move right;
47 left = mid;
48 } else {
49 right = mid;
50 }
51 }
52
53 if (A[right] == target) {
54 ret[1] = right;
55 } else if (A[left] == target) {
56 ret[1] = left;
57 } else {
58 return ret;
59 }
60
61 return ret;
62 }
63 }
别人挺好的方法:
public int[] searchRange(int[] A, int target) {
int[] result = new int[2];
result[0] = -1;
result[1] = -1;
if(A[0]>target || A[A.length-1]<target) return result;
int low = 0;
int high = A.length-1;
while(low<=high){
int mid = low+(high-low)/2;
if(A[mid]==target){
high = mid;
low = mid;
while(low>=0&&A[low]==target){
low--;
}
result[0]=low+1;
while(high<A.length&&A[high]==target){
high++;
}
result[1] = high-1;
return result;
}else if(A[mid]>target){
high = mid-1;
}else {
low = mid+1;
}
}
return result;
}
public int[] searchRange(int[] A, int target) {
int[] result = new int[2];
result[0] = getBoundRange(A, 0, A.length-1, target, true);
result[1] = getBoundRange(A, 0, A.length-1, target, false);
return result;
}
public int getBoundRange(int[]A, int l, int r, int target, boolean left){
if(l>r) return -1;
else{
int m = (l+r)/2;
if(A[m]==target){
if(left){
if(m==0 || A[m-1]<target) return m;
else return getBoundRange(A, l, m-1, target, left);
}else {
if(m==A.length-1 || target<A[m+1]) return m;
else return getBoundRange(A, m+1, r, target, left);
}
}
else if (A[m]>target) {
return getBoundRange(A, l, m-1, target, left);
}else {
return getBoundRange(A, m+1, r, target, left);
}
}
}