(34)Search for a Range
题目:给定升序排序的整数数组,找到给定目标值的起始和终止位置,算法运行时间复杂度必须为O(logn)的时间复杂度,如果在数组中找不到目标,则返回[-1, -1]。
例如:
给定数组为[5, 7, 7, 8, 8, 10]和目标值8,
返回[3, 4]。
根据这道题的思路,最开始打算找整个目标数组的位置,这让就能得到整个数组的首尾,但是后来发现两端的处理并不是很容易,所以选择了2*O(logn)的方法就是分别求两端的位置。
看到O(logn)就应该知道是二分法了,然后再二分的过程中,分别找左端和右端位置,拿左端为例:当中位数是大于或等于目标数字的时候,由于已经是排好序的,那么就递归查找左半侧,当中位数是小于目标数字的时候,递归查找右半侧;右端的时候就分为中位数大于,小于等于两种可能,为什么自己画图考虑一下就明白了。
下面是代码:
class Solution {
public:
int search_left(vector<int> nums, int left_num, int right_num, int target){
int mid = (left_num + right_num) / 2;
if(nums[left_num] == target){
return left_num;
}
if(left_num == right_num){
if(target == nums[left_num]){
return left_num;
}
else{
return -1;
}
}
if(left_num + 1 == right_num){
if(target == nums[left_num]){
return left_num;
}
else if(target == nums[right_num]){
return right_num;
}
else{
return -1;
}
}
if(nums[mid] >= target){
return search_left(nums, left_num, mid, target);
}
else if(nums[mid]<target){
return search_left(nums, mid, right_num, target);
}
}
int search_right(vector<int> nums, int left_num, int right_num, int target){
int mid = (left_num + right_num) / 2;
if(nums[right_num] == target){
return right_num;
}
if(left_num == right_num){
if(target == nums[right_num]){
return right_num;
}
else{
return -1;
}
}
if(left_num + 1 == right_num){
if(target == nums[right_num]){
return right_num;
}
else if(target == nums[left_num]){
return left_num;
}
else{
return -1;
}
}
if(nums[mid] <= target){
return search_right(nums, mid, right_num, target);
}
else if(nums[mid]>target){
return search_right(nums, left_num, mid, target);
}
}
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.size()==0){
vector<int> v;
v.push_back(-1);
v.push_back(-1);
return v;
}
int lef = search_left(nums, 0, nums.size()-1, target);
int rig = search_right(nums, 0, nums.size()-1, target);
vector<int> v;
v.push_back(lef);
v.push_back(rig);
return v;
}
};