题目表述
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
来源:力扣(LeetCode)
链接:leetcode.cn/problems/fi…
难点分析
-
按照题目要求,可以分为如下四种情况处理:
- 情况0:数组没有元素:
if(nums.size() == 0) return {-1, -1};
- 情况一:target数值在非递减数组两端之外:return {-1, -1}
- 解法:直接判断target是否小于排序数组最小元素,或大于排序数组最大元素。
if(target < nums[0] || target > nums[nums.size() - 1]) return {-1, -1};
- 解法:直接判断target是否小于排序数组最小元素,或大于排序数组最大元素。
- 情况二:target数值在数组两端内,但target值不在数组中:return {-1, -1}
- 情况三:target数值在数组中可以找到:return {left, right}
- 情况0:数组没有元素:
-
对于情况二和三,我们采用二分法。
- 根据普通的二分查找,我们可以轻而易举找到该元素在数组中的下标,接下来,继续二分查找,寻找左右边界。
- 寻找左边界:当找到与target相等元素时可知,最左元素的上一个位置一定在target左边,于是继续向左寻找
right = mid - 1; - 寻找右边界:当找到与target相等元素时可知,最右元素的下一个位置一定在target右边,于是继续向右寻找
left = mid + 1; - 为什么是最左右元素的下一个位置?
- 这里采用左闭右闭区间,当利用原while循环继续寻找时,执行
right = mid - 1;,left = mid + 1;,因此是下一位置。
- 这里采用左闭右闭区间,当利用原while循环继续寻找时,执行
- 第二种情况:由于我们计算出的左右边界是左右端的下一位置,因此,若情况二出现,二分查找中应该找到同一位置,左右边界应该重合,有:
if(left == right) return {-1, -1};
- 第三种情况,返回计算的左右边界即可。