给你一个按照非递减顺序排列的整数数组 nums
,和一个目标值 target
。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target
,返回 [-1, -1]
。
你必须设计并实现时间复杂度为 O(log n)
的算法解决此问题。
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
输入:nums = [], target = 0
输出:[-1,-1]
二分查找思路解释:
这样,代码通过两次二分查找,可以找到目标值在数组中的起始位置和结束位置,并且满足了 O(log n) 的时间复杂度要求。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.empty()){
return {-1, -1};
}
vector<int> result(2, -1);
int n = nums.size();
int l = 0,r= n-1;
while(l<r){
int mid = (l+r)>>1;
if(nums[mid]>=target)r=mid;
else l = mid+1;
}
if(nums[l]!=target)return {-1,-1};
else {
result[0]=l;
l=0,r=n-1;
while(l<r){
int mid = (l+r+1)>>1;
if(nums[mid]<=target)l=mid;
else r=mid-1;
}
result[1]=l;
return result;
}
}
};
下面是代码的执行效率
当然我们也可以用更简便的二分查找lower_bound()
和 upper_bound()
函数求解:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
auto first = lower_bound(nums.begin(), nums.end(), target);
auto last = upper_bound(nums.begin(), nums.end(), target);
if (first == nums.end() || *first != target) {
return {-1, -1};
} else {
return {static_cast<int>(first - nums.begin()), static_cast<int>(last - nums.begin() - 1)};
}
}
};
这段代码实现了在一个按非递减顺序排列的整数数组中查找目标值的起始位置和结束位置,使用了 C++ 标准库中的 lower_bound() 和 upper_bound() 函数。下面是代码的解释:
首先,使用 lower_bound(nums.begin(), nums.end(), target) 函数在排序后的数组 nums 中找到第一个不小于目标值 target 的元素的迭代器,赋值给变量 first。
然后,使用 upper_bound(nums.begin(), nums.end(), target) 函数在排序后的数组 nums 中找到第一个大于目标值 target 的元素的迭代器,赋值给变量 last。
接着,通过比较 first 是否等于 nums.end() 或 *first 是否等于 target,来判断是否找到了目标值:
最后,根据找到的位置返回结果:
通过使用 lower_bound() 和 upper_bound() 函数,可以非常简洁地实现在排序数组中查找目标值的起始位置和结束位置,避免了手动编写二分查找的复杂逻辑。
但是执行效率不如手写二分查找高