给定一个排序数组nums(nums中有重复元素)与目标值target,如果 target在nums里出现,则返回target所在区间的左右端点下标,[左端点, 右端 点],如果target在nums里未出现,则返回[-1, -1]。
LeetCode 34. Search for a Range
思考
1.可否直接通过二分查找,很容易同时求出目标target所在区 间的左右端点? 2.若无法同时求出区间左右端点,将对目标target的二分查找 增加怎样的限制条件,就可分别求出目标target所在区间 的左端点与右端点?
算法设计
查找区间左端点时,增加如下限制条件:
当target == nums[mid]时,若此时mid == 0或nums[mid-1] < target,则说明mid即 为区间左端点,返回;否则设置区间右端点为mid-1。
查找区间右端点时,增加如下限制条件:
当target == nums[mid]时,若此时mid == nums.size() – 1或 nums[mid + 1] > target ,则说明mid即为区间右端点;否则设置区间左端点为mid + 1
流程:
int left_bound(std::vector<int> &nums, int target){
int begin = 0;
int end = noms.size() -1 ;
while(begin <= end){
int mid = (begin + end) / 2;
if(target == nums[mid]){
if(mid == 0 || target > nums[mid-1]){
return mid;
}
begin = mid + 1;
}
else if(target < nums[mid]){
end = mid -1;
}
else if(target > nums[mid]){
begin = mid +1;
}
}
return -1;
}
区间右端点
int right_bound(std::vector<int> &nums,int target){
int begin = 0;
int end = nums.size() -1;
while(begin <= end){
int mid =( begin + end )/2;
if(target == mid){
if(mid = nums.size()-1 || nums[mid+1] > target){
return mid;
}
begin = mid +1;
}
else if(target < nums[mid]){
end = mid -1;
}
else if(target > nums[mid]){
begin = mid+1;
}
}
return -1;
}
leetcode测试
class Solution{
public:
std::vector<int> searchRange(std::vector<int>&nums, int target){
std::vector<int> result;
result.push_back(left_bound(nums,target));
result.push_back(right_bound(nums,target));
return result;
}
};
int main(){
int test[] = {5,7,7,8,8,8,8,10};
std::vector<int> nums;
Solution solve;
for(int i = 0;i< 8;i++){
nums.push_back(test[i]);
}
for(int i= 0;i< 12;i++){
std::vector<int> result = solve.searchRange(nums,i);
printf("%d : [%d,%d]\n",i, result[0],result[i]);
}
return 0;
}