1. 思路
(1)时间复杂度O(log n):这是一道需要用二分法解决的问题。
(2)这是一个非递减的数组:可能有多于1个的目标值连续出现。当找到了一个目标之后,连续目标值的首尾可以通过排除目标值的方法来搜索。
(3)考虑有目标值的情况:
- 找到目标数组的开始/结束位置:翻译过来就是找到一个值,既要等于目标值,左边/右边不是目标值。
- 搜索开始位置时,当搜索到目标值,将右端点更新到中值左边,缩小区间,直到所有目标值都被排除。取左端点作为结束。
- 结束为止同理,当搜索到目标值,将左端点更新到中值右边,取右端点作为结束。
(4)没有目标值的情况:直接输出{-1, -1}。
2. 代码
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
// 首先给左边界初始化,然后找左边界,并赋值,最后返回左边界
int left = 0;
int right = nums.size() - 1;
int first = -1;
while (left <= right) {
int mid = left + ((right - left)>>1);
if (nums[mid] == target) {
first = mid;
right = mid -1;
}
else if (nums[mid] > target) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
// 右边界,
left = 0;
right = nums.size() - 1;
int last = -1;
while (left <= right) {
int mid = left + ((right - left)>>1);
if (nums[mid] == target) {
last = mid;
left = mid + 1;
}
else if (nums[mid] > target) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
return {first, last};
}
};
tips
1. 给开始值first和结束值last初始化为 -1。由此可以统一输出为{first, last}。