1,题目要求
Given an array of integers nums 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(logn)
.
If the target is not found in the array, return[-1, -1]
.
Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
给定按升序排序的整数数组,找到给定目标值的起始位置和结束位置。
算法的运行时复杂度必须是O(logn)
的顺序。
2,题目思路
对于这道题,题目是在一个已经排序的数组内,找到对应元素的第一个和最后一个出现的位置。
如果我们使用STL内置的方法,即:
lower_bound
upper_bound
问题可以得到轻松的解决。
而如果我们自己实现,也可以实现类似的功能,不过题目要求时间复杂度为O(logn)
,因此,对于查找而言,满足条件的自然是二分查找。
而在二分查找上,因为我们不是找到这个元素,而是为了找到第一个比target小的元素,因此,判定条件部分为:
while(low <= high){
int mid = low + (high - low)/2;
if(nums[mid] < target)
low = mid+1;
else
high = mid-1;
}
另外一种思路则是在于,因为这个数组是有序的,因此,我们要查找的target要么不在数组中,要么只有一个。
而如果在数组中有多个target出现,则它们一定是连续出现的。这样,我们只需要使用二分查找的办法在target中找到对应的元素位置,然后分别向前和向后探索,找到target的边界,也可以得到最终的结果。
3,代码实现
1,STL
int x = []() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
return 0;
}();
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
auto it1 = std::lower_bound(nums.begin(), nums.end(), target);
auto it2 = std::upper_bound(nums.begin(), nums.end(), target);
if (it1 != nums.end() && *it1 == target)
return {it1 - nums.begin(), it2 - nums.begin() - 1};
return {-1, -1};
}
};
2,二分查找实现lower_bound
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int left = myLower_bound(nums, target, 0, nums.size()-1);
int right = myLower_bound(nums, target+1, 0, nums.size()-1)-1;
//之所以要添加left < nums.size(),是为了排除nums = []的情况
//因为这种情况下,left = 0,nums.size() = 0,因此可以排除
if(left < nums.size() && nums[left] == target)
return {left, right};
return {-1,-1};
}
private:
int myLower_bound(vector<int>& nums, int target, int low, int high){
while(low <= high){
int mid = low + (high - low)/2;
if(nums[mid] < target)
low = mid+1;
else
high = mid-1;
}
return low;
}
};
3,二分查找+前后探索
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int index = binarySearch(nums, target, 0, nums.size()-1);
vector<int> res {-1,-1};
if(index == -1)
return res;
else
{
int left = index;
int right = index;
while(left >= 0 && nums[left] == target ) left--;
while(right<=nums.size()-1 && nums[right] == target) right++;
res[0] = left+1, res[1] = right-1;
}
return res;
}
private:
int binarySearch(vector<int>& nums, int target, int low, int high) {
while(low <= high){
int mid = low + (high - low)/2;
if(nums[mid] == target)
return mid;
else if(nums[mid] < target)
low = mid+1;
else
high = mid-1;
}
return -1;
}
};