题目
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 <br>
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8 输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6 输出:[-1,-1]
示例 3:
输入:nums = [], target = 0 输出:[-1,-1]
提示:
0 <= nums.length <= 105 -109 <= nums[i] <= 109 nums 是一个非递减数组 -109 <= target <= 109
分析:
根据题目给定一个非递减的数组,在其中查找目标值target,那我们应该想到二分算法,并且题目要求的时间复杂度为 O(log n) ,而二分算法的时间复杂度正好是 O(log n) ; 具体的,由于是查找target的范围,而二分算法只能查找一个值,因此我们可以调用两次二分算法:
- 第一次查找target的开始位置start,如果start等于n(即nums数组没有target)或查找的nums[start] != target,则表示nums中没有target,返回{-1, -1};
- 否则进行第二次查找,我们可以查找比target大于1的值的开始位置start_big,而start_big - 1就是target的结束位置end,返回{start, end}。
AC代码:
class Solution {
int lowerBound(vector<int>& nums, int target) {
int n = nums.size();
int left = -1, right = n;
while (left + 1 < right) {
int mid = (right - left) / 2 + left;
if (nums[mid] >= target) {
right = mid;
} else {
left = mid;
}
}
return right;
}
public:
vector<int> searchRange(vector<int>& nums, int target) {
int start = lowerBound(nums, target);
if (start == nums.size() || nums[start] != target) {
return {-1, -1};
}
int end = lowerBound(nums, target + 1) - 1;
return {start, end};
}
};