1、左右区间要单独查找,时间复杂度为
O
(
l
o
g
N
)
O(logN)
O(logN)
2、查找右边界的时候,左边向右收缩;查找左边界的时候,右边向左收缩。
class Solution {
public:
int getR(vector<int>& nums, int target){
int l = 0, r = nums.size()-1;
int rightborder = -1;
while (l <= r){
int mid = l + (r - l)/2;
if (nums[mid] == target){
l = mid + 1;
rightborder = mid;
}else if (nums[mid] > target){
r = mid - 1;
}else {
l = mid + 1;
}
}
return rightborder;
}
int getL(vector<int>& nums, int target){
int l = 0, r = nums.size()-1;
int leftborder = -1;
while (l <= r){
int mid = l + (r - l)/2;
if (nums[mid] == target){
r = mid - 1;
leftborder = mid;
}else if (nums[mid] > target){
r = mid - 1;
}else {
l = mid + 1;
}
}
return leftborder;
}
vector<int> searchRange(vector<int>& nums, int target) {
int leftborder = getL(nums, target);
int rightborder = getR(nums, target);
return {leftborder, rightborder};
}
};
我的困惑:
if (target == nums[mid]) {
ans = mid;
right = mid - 1;
}
为什么这里是right = mid -1,而不是right = mid;
GPT解答:
在getL函数中,当找到一个等于target的元素时,我们需要继续往左边搜索,以找到所有等于target的元素中最左边的一个。
如果将right = mid
,那么下一次循环中,mid的值还是等于上一次的mid,即等于已经找到的最左边的target元素的位置,这样会导致搜索过程陷入死循环,无法继续往左边搜索。
因此,我们需要将right
的值更新为mid-1
,这样可以确保下一次循环中的mid
值一定在左边,并且不会重复搜索已经找到的最左边的target元素。
我的困惑:
如果将right = mid,那么下一次循环中,mid的值还是等于上一次的mid,即等于已经找到的最左边的target元素的位置,这样会导致搜索过程陷入死循环,无法继续往左边搜索。
这段话没有懂,可以举一个例子吗
GPT解答:
当我们将 right = mid
的时候,如果出现下面这种情况:
[1, 2, 3, 4, 5, 5, 5, 6],target = 5
首先我们将 left = 0
,right = 7
,mid = 3
,此时 nums[mid] = 4 < target
,所以我们将 left
更新为 mid + 1 = 4
。
接着,left = 4
,right = 7
,mid = 5
,此时 nums[mid] = 5 = target
,我们将 ans
更新为 mid
,并将 right
更新为 mid
,即 right = 5
。
现在,我们再次进入循环,left = 4
,right = 5
,mid = 4
,此时 nums[mid] = 5 = target
,我们将 ans
更新为 mid
,并将 right
更新为 mid
,即 right = 4
。
下一次循环中,left = 4
,right = 4
,mid = 4
,此时 nums[mid] = 5 = target
,我们将 ans
更新为 mid
,并将 right
更新为 mid
,即 right = 4
。
此时,我们发现 left
和 right
的值已经相等了,但是我们不能退出循环,因为我们还没有找到最左边的target元素,而且我们也无法继续向左边查找。
这样,我们就陷入了死循环,无法继续向左边查找,也无法找到最左边的target元素。