给你一个按照非递减顺序排列的整数数组
nums,和一个目标值target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值
target,返回[-1, -1]。你必须设计并实现时间复杂度为
O(log n)的算法解决此问题。示例 1:
输入:nums = [5,7,7,8,8,10], target = 8 输出:[3,4]
- 1
- 2
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6 输出:[-1,-1]
- 1
- 2
示例 3:
输入:nums = [], target = 0 输出:[-1,-1]
- 1
- 2
提示:
0 <= nums.length <= 105-109 <= nums[i] <= 109nums是一个非递减数组-109 <= target <= 109
x表示该元素,resLest表示左边界,resRight表示右边界x的x的mid的落点情况如下:
mid落在[left,resLeft-1]区间的时候,也就是arr[mid],说明[left,mid]都是可以舍去的,此时更新left到mid+1的位置,继续在[mid+1,right]上寻找左边界 mid落在[resLeft,right]的区间的时候,也就是arr[mid]>=target,说明[mid+1,right](因为mid可能是最终结果,不能舍去)是可以舍去的,此时更新right到mid的位置,继续[left,mid]上寻找左边界注意事项:找中间元素需要向下取整
因为后续继续移动指针的时候:
左指针:
left=mid+1,是会向后移动的,因此区间是会缩小的右指针:
right=mid,可能会原地踏步(比如:如果向上取整的话,如果剩下1,2两个元素的,left==1,right==2,mid==2。更新区间之后,left,right,mid的值没有改变,就会陷入死循环)
x表示该元素,resLest表示左边界,resRight表示右边界[left,resRight]都是小于等于x的[resRight+1,right]都是大于x是的mid的落点情况如下:
mid落在[left,resRight]区间的时候,也就是arr[mid]<=target,说明[left,mid-1](mid不可以舍去,因为有可能是最终结果)都是可以舍去的,此时更新left到mid的位置mid落在[resRight+1,right]的区间的时候,也就是arr[mid]>target,说明[mid,right]内的元素是可以舍去的,此时更新right到mid-1的位置注意事项:找中间元素需要向上取整
因为后续继续移动指针的时候:
左指针:
left = mid,可能会原地踏步(⽐如:如果向下取整的话,如果剩下1,2两个元
素,left == 1, right == 2,mid == 1。更新区间之后,left,right,mid的值
没有改变,就会陷⼊死循环)。
右指针:right = mid - 1,是会向前移动的,因此区间是会缩⼩的;
因此⼀定要注意,当right = mid的时候,要向下取整。
left为0,右指针right为数组长度减1。left小于右指针right,计算中间位置mid,如果中间位置的元素小于目标元素,则目标元素可能在右半部分,更新左指针left为mid + 1。如果中间位置的元素大于等于目标元素,则目标元素可能在左半部分,更新右指针right为mid。循环结束后,左指针left指向的位置就是目标元素的起始位置。left指向的元素不等于目标元素,则不存在目标元素,返回{-1, -1}表示无解。begin中。left为0,右指针right为数组长度减1。循环条件是左指针left小于右指针right,计算中间位置mid,如果中间位置的元素大于目标元素,则目标元素可能在左半部分,更新右指针right为mid - 1。如果中间位置的元素小于等于目标元素,则目标元素可能在右半部分,更新左指针left为mid。循环结束后,右指针right指向的位置就是目标元素的结束位置。
class Solution {
public:
vector searchRange(vector& nums, int target) {
//处理边界情况
if(nums.size()==0) return {-1,-1};
int begin=0;
//二分左端点
int left=0,right=nums.size()-1;
while(lefttarget) right=mid-1;
else left=mid;
}
return {begin,right};
}
};