题目:Given a sorted array of integers, 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].
解析1:我们可以使用 c++ STL 提供的 lower_bound 和 upper_bound 函数来求解这个问题。
代码如下:
// 使用 STL 中提供的 lower_bound 和 upper_bound 函数
// upper_bound 返回一个迭代器,指向[first, last) 中第一个大于 target 的元素
// lower_bound 返回一个迭代器,指向[first, last) 中打一个大于等于 target 的元素
// 因此如果 tagret 在 [first, last) 范围内不存在
// 则 lower_bound 与 upper_bound 应返回相同的迭代器
// 时间复杂度为 O(logn)
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
auto lower = lower_bound(nums.begin(), nums.end(), target);
auto upper = upper_bound(lower, nums.end(), target);
// target 在数组 nums 中不存在
if (lower == upper) return vector<int>{-1, -1};
// target 在数组 nums 中存在
const int l = distance(nums.begin(), lower);
const int u = distance(nums.begin(), prev(upper));
return vector<int>{l, u};
}
};
解析2:我们可以自己写代码实现 lower_bound 和 upper_bound 函数,代码如下:
// 不借助于 STL,自己实现 lower_bound 和 upper_bound
// 时间复杂度 O(logn),空间复杂度 O(1)
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
auto lower = lower_bound(nums.begin(), nums.end(), target);
auto upper = upper_bound(lower, nums.end(), target);
// target 在数组 nums 中不存在
if (lower == upper) return vector<int>{-1, -1};
// target 在数组 nums 中存在
const int l = distance(nums.begin(), lower);
const int u = distance(nums.begin(), prev(upper));
return vector<int>{l, u};
}
private:
template<class ForwardIterator, class T>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, T target) {
while (first != last) {
size_t len = last - first;
auto mid = next(first, len / 2);
if (*mid < target) first = ++mid;
else last = mid;
}
return first;
}
template <class ForwardIterator, class T>
ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, T target) {
while (first != last) {
size_t len = last - first;
auto mid = next(first, len / 2);
if (*mid <= target) first = ++mid;
else last = mid;
}
return first;
}
};