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
For example,
Given
return
X.
https://discuss.leetcode.com/topic/6327/a-very-simple-java-solution-with-only-one-binary-search-algorithm
X. With only one binary search algorithm - not efficient
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]
.X.
https://discuss.leetcode.com/topic/6327/a-very-simple-java-solution-with-only-one-binary-search-algorithm
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;
}
https://discuss.leetcode.com/topic/16486/9-11-lines-o-log-nX. With only one binary search algorithm - not efficient
http://www.programcreek.com/2014/04/leetcode-search-for-a-range-java/
public int[] searchRange(int[] nums, int target) { if(nums == null || nums.length == 0){ return null; } int[] arr= new int[2]; arr[0]=-1; arr[1]=-1; binarySearch(nums, 0, nums.length-1, target, arr); return arr; } public void binarySearch(int[] nums, int left, int right, int target, int[] arr){ if(right<left) return; if(nums[left]==nums[right] && nums[left]==target){ arr[0]=left; arr[1]=right; return; } int mid = left+(right-left)/2; if(nums[mid]<target){ binarySearch(nums, mid+1, right, target, arr); }else if(nums[mid]>target){ binarySearch(nums, left, mid-1, target, arr); }else{ arr[0]=mid; arr[1]=mid; //handle duplicates - left int t1 = mid; while(t1 >left && nums[t1]==nums[t1-1]){ t1--; arr[0]=t1; } //handle duplicates - right int t2 = mid; while(t2 < right&& nums[t2]==nums[t2+1]){ t2++; arr[1]=t2; } return; }
https://leetcode.com/discuss/29228/simple-and-strict-o-logn-solution-in-java-using-recursion
public int[] searchRange(int[] A, int target) { int[] range = {A.length, -1}; searchRange(A, target, 0, A.length - 1, range); if (range[0] > range[1]) range[0] = -1; return range; } public void searchRange(int[] A, int target, int left, int right, int[] range) { if (left > right) return; int mid = left + (right - left) / 2; if (A[mid] == target) { if (mid < range[0]) { range[0] = mid; searchRange(A, target, left, mid - 1, range); } if (mid > range[1]) { range[1] = mid; searchRange(A, target, mid + 1, right, range); } } else if (A[mid] < target) { searchRange(A, target, mid + 1, right, range); } else { searchRange(A, target, left, mid - 1, range); } }
X.
https://leetcode.com/discuss/18242/clean-iterative-solution-binary-searches-with-explanation
https://leetcode.com/discuss/52701/easy-java-o-logn-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; }
如果我们不寻找那个元素先,而是直接相等的时候也向一个方向继续夹逼,如果向右夹逼,最后就会停在右边界,而向左夹逼则会停在左边界,如此用停下来的两个边界就可以知道结果了,只需要两次二分查找
http://www.jiuzhang.com/solutions/search-for-a-range/
https://leetcode.com/discuss/19368/very-simple-java-solution-with-only-binary-search-algorithm
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;
}
X. http://www.cnblogs.com/springfor/p/3857704.html
Read full article from 西小瓜: Leetcode: Search for a Range
public int[] searchRange(int[] A, int target) { int[] range = {A.length, -1}; searchRange(A, target, 0, A.length - 1, range); if (range[0] > range[1]) range[0] = -1; return range; } public void searchRange(int[] A, int target, int left, int right, int[] range) { if (left > right) return; int mid = left + (right - left) / 2; if (A[mid] == target) { if (mid < range[0]) { range[0] = mid; searchRange(A, target, left, mid - 1, range); } if (mid > range[1]) { range[1] = mid; searchRange(A, target, mid + 1, right, range); } } else if (A[mid] < target) { searchRange(A, target, mid + 1, right, range); } else { searchRange(A, target, left, mid - 1, range); } }
X.
https://leetcode.com/discuss/18242/clean-iterative-solution-binary-searches-with-explanation
https://leetcode.com/discuss/52701/easy-java-o-logn-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; }
如果我们不寻找那个元素先,而是直接相等的时候也向一个方向继续夹逼,如果向右夹逼,最后就会停在右边界,而向左夹逼则会停在左边界,如此用停下来的两个边界就可以知道结果了,只需要两次二分查找
http://www.jiuzhang.com/solutions/search-for-a-range/
public int[] searchRange(int[] A, int target) { if (A.length == 0) { return new int[]{-1, -1}; } int start, end, mid; int[] bound = new int[2]; // search for left bound start = 0; end = A.length - 1; while (start + 1 < end) { mid = start + (end - start) / 2; if (A[mid] == target) { end = mid; } else if (A[mid] < target) { start = mid; } else { end = mid; } } if (A[start] == target) { bound[0] = start; } else if (A[end] == target) { bound[0] = end; } else { bound[0] = bound[1] = -1; return bound; } // search for right bound start = 0; end = A.length - 1; while (start + 1 < end) { mid = start + (end - start) / 2; if (A[mid] == target) { start = mid; } else if (A[mid] < target) { start = mid; } else { end = mid; } } if (A[end] == target) { bound[1] = end; } else if (A[start] == target) { bound[1] = start; } else { bound[0] = bound[1] = -1; return bound; } return bound; }http://www.lifeincode.net/programming/leetcode-search-for-a-range-java/
public int[] searchRange(int[] A, int target) {
int[] ret = {-1, -1};
int start = 0;
int end = A.length - 1;
while (start < end) {
int mid = (start + end) / 2;
if (A[mid] < target)
start = mid + 1;
else
end = mid;
}
int low;
if (A[start] != target)
return ret;
else
low = start;
start = 0;
end = A.length - 1;
while (start < end) {
int mid = (start + end) / 2;
if (A[mid] < target + 1)
start = mid + 1;
else
end = mid;
}
int high = A[start] == target ? start : start - 1;
ret[0] = low;
ret[1] = high;
return ret;
}
https://leetcode.com/discuss/19368/very-simple-java-solution-with-only-binary-search-algorithm
basically it is the same idea with using separate binary search for left and right bounds. The good point here is the lower_bound and the search for (target+1)
X. http://www.cnblogs.com/springfor/p/3857704.html
第一步,在给定数组中找到该target,记录该位置。这时我们并不关心这个target是边界还是中间值,我们只需确定,在数组中是能够找到这样一个target值。如果找不到返回{-1,-1}。为了保证时间复杂度是O(logn), 这里自然而然使用传统二分查找法实现。
第二步,确定该target的右边界。此时我们将对数组从刚才确定的那个target的pos作为起始点,到数组结束,来确定右边界。同样是使用二分查找法,当新的mid值仍然等于target值时,我们能确定该mid左半边(到pos)都是等于target,继续在右半边查找。如果新的mid值不等于target值,我们就知道右边界一定在新mid值的左半边,继续查找。最后新的high指针指向的就是右边界的位置。
第三步,确定该target的左边界。这一步与第二步对称操作,最后新的low指针指向的就是左边界的位置。
1 public int[] searchRange(int[] A, int target) {
2 int [] res = {-1,-1};
3 if(A == null || A.length == 0)
4 return res;
5
6 //first iteration, find target wherever it is
7 int low = 0;
8 int high = A.length-1;
9 int pos = 0;
10 while(low <= high){
11 int mid = (low + high)/2;
12 pos = mid;
13 if(A[mid] > target)
14 high = mid - 1;
15 else if(A[mid] < target)
16 low = mid + 1;
17 else{
18 res[0] = pos;
19 res[1] = pos;
20 break;
21 }
22 }
23
24 if(A[pos] != target)
25 return res;
26
27 //second iteration, find the right boundary of this target
28 int newlow = pos;
29 int newhigh = A.length-1;
30 while(newlow <= newhigh){
31 int newmid = (newlow+newhigh)/2;
32 if(A[newmid] == target)
33 newlow = newmid + 1;
34 else
35 newhigh = newmid - 1;
36 }
37 res[1] = newhigh;
38
39 //third iteration, find the left boundary of this target
40 newlow = 0;
41 newhigh = pos;
42 while(newlow <= newhigh){
43 int newmid = (newlow+newhigh)/2;
44 if(A[newmid] == target)
45 newhigh = newmid - 1;
46 else
47 newlow = newmid + 1;
48 }
49 res[0] = newlow;
50
51 return res;
52 }
http://www.darrensunny.me/leetcode-search-for-a-range/2 int [] res = {-1,-1};
3 if(A == null || A.length == 0)
4 return res;
5
6 //first iteration, find target wherever it is
7 int low = 0;
8 int high = A.length-1;
9 int pos = 0;
10 while(low <= high){
11 int mid = (low + high)/2;
12 pos = mid;
13 if(A[mid] > target)
14 high = mid - 1;
15 else if(A[mid] < target)
16 low = mid + 1;
17 else{
18 res[0] = pos;
19 res[1] = pos;
20 break;
21 }
22 }
23
24 if(A[pos] != target)
25 return res;
26
27 //second iteration, find the right boundary of this target
28 int newlow = pos;
29 int newhigh = A.length-1;
30 while(newlow <= newhigh){
31 int newmid = (newlow+newhigh)/2;
32 if(A[newmid] == target)
33 newlow = newmid + 1;
34 else
35 newhigh = newmid - 1;
36 }
37 res[1] = newhigh;
38
39 //third iteration, find the left boundary of this target
40 newlow = 0;
41 newhigh = pos;
42 while(newlow <= newhigh){
43 int newmid = (newlow+newhigh)/2;
44 if(A[newmid] == target)
45 newhigh = newmid - 1;
46 else
47 newlow = newmid + 1;
48 }
49 res[0] = newlow;
50
51 return res;
52 }
public int[] searchRange(int[] A, int target) {
int[] result = {-1, -1};
int n = A.length;
if (A == null || n == 0)
return result;
// Find one target first
int separator = -1; // The index of one of several appearances of target
int left = 0, right = n-1;
while (left <= right) {
int middle = (left+right) / 2;
if (A[middle] > target) { // target must be at the left half
right = middle - 1;
} else if (A[middle] < target) { // target must be at the right half
left = middle + 1;
} else { // Find one target
separator = middle;
break;
}
}
if (separator == -1) // No target exists
return result;
// Find the starting index within A[0...separator]
left = 0;
right = separator;
while (left <= right) {
int middle = (left+right) / 2;
if (A[middle] == target) // right will end up at right before the starting index
right = middle - 1;
else // A[middle]<target; the starting index should be within [middle+1,right]
left = middle + 1;
} // out of loop; left = right - 1, i.e. the starting index
result[0] = left; // Save the starting index in result[0]
// Find the ending index within A[separator+1...n-1]
left = separator;
right = n - 1;
while (left <= right) {
int middle = (left+right) / 2;
if (A[middle] == target) // left will end up at right after the ending index
left = middle + 1;
else // A[middle]>target; the starting index should be within [left, middle-1]
right = middle - 1;
} // out of loop; right = left + 1, i.e. the ending index
result[1] = right; // Save the ending index in result[1]
return result;
}
Also check http://zhaohongze.com/wordpress/2014/01/05/leetcode-search-for-a-range/Read full article from 西小瓜: Leetcode: Search for a Range