Given an array of integers 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]
.
For example,
Given [5, 7, 7, 8, 8, 10]
and target value 8,
return [3, 4]
.
由题意,是要求:在一个给定的非降序整型数组nums中,给定一个目标值target,求出数组中该值的起始位置索引和结束位置索引。要求算法的时间复杂度为O(log N)。
分析:看到时间复杂度为O(log N),立即联想到这是个典型的二分法查找的应用问题。不过在本题中,因为要求得左右边界位置,不能简单地使用二分查找法,而需要进行一定的修改。
修改的方法是:改进二分查找法,终止条件变为:left < right - 1;而当前值与目标值相等时,求左边界就把当前索引下标赋给 right,求右边界就把当前索引下标赋给 left,即让 left--right 区间向目标边界靠拢。这样,结束的时候,会有2个值供我们判断使用。这样做的最大的好处是,不用处理各种越界问题。编写代码时要注意,求左边界时,优先判断 left 是否为边界,再判断 right;而求右边界时,优先判断 right 是否为边界,再判断 left。
给出AC的JAVA代码如下:
public class Solution {
public int[] searchRange(int[] nums, int target) {
int len = nums.length;
int left = 0;
int right = len-1;
int[] res = {-1, -1};
// corner case
if (len==0||nums==null) {
return res;
}
// binary search loop, when loop end, there will be 2 elements between left and right index
while (left<right-1) {
// search the left bound
int mid = (right+left)/2;
if(nums[mid] == target){
right = mid;
} else if(nums[mid] < target) {
left = mid;
} else {
right = mid;
}
}
// set the left bound
if (nums[left]==target) {
res[0]=left;
} else if (nums[right]==target) {
res[0]=right;
} else {
return res;
}
// reset the left and right index
left=0;
right=len-1;
// search the right bound
while (left<right-1) {
int mid=(right+left)/2;
if (nums[mid]==target) {
left=mid;
} else if (nums[mid] < target) {
left=mid;
} else {
right = mid;
}
}
// set the right bound
if (nums[right]==target) {
res[1]=right;
} else if (nums[left]==target) {
res[1]=left;
} else {
return res;
}
return res;
}
}