问题:
给你一个按照非递减顺序排列的整数数组 nums
,和一个目标值 target
。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target
,返回 [-1, -1]
。
你必须设计并实现时间复杂度为 O(log n)
的算法解决此问题。
示例 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]
解答:由于题目要求时间复杂度为O(log n)
,而数组为从小到大排序,因此很容易想到用二分法进行查找。不同的是,普通的二分法查到target目标值后直接返回,而该题目还需要继续查找最左边和最右边的值。
为了把整体思路完全表示出来,解答代码中有很多冗余的部分,但是整体可读性得到加强。解题代码如下所示:
class Solution {
public:
int find_position(vector<int>& nums, int target, bool is_first) {
int len = nums.size();
int left = 0;
int right = len - 1;
int ans = -1;
while (left < right) {
int mid = (left + right) >> 1;
if (is_first) {
if (target < nums[mid]) {
right = mid - 1;
} else if (target == nums[mid]) {
ans = mid;
right = mid;
} else {
left = mid + 1;
}
} else {
if (target < nums[mid]) {
right = mid - 1;
} else if (target == nums[mid]) {
ans = mid;
left = mid + 1;
} else {
left = mid + 1;
}
}
}
if(nums[left] == target){
ans = left;
}
return ans;
}
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> res = {-1, -1};
if (nums.size() == 0) {
return res;
}
if (nums.size() == 1 && nums[0] == target) {
res = {0, 0};
return res;
}
int left = find_position(nums, target, true);
int right = find_position(nums, target, false);
res = {left, right};
return res;
}
};