难度:中等
给你一个按照非递减顺序排列的整数数组 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]
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums
是一个非递减数组-109 <= target <= 109
一、模式识别
排序数组 》 二分查找
开始结束位置 》 前后试探
二、代码实现
1.推荐方法:二分查找 + 前后试探
该方法思路清晰且模式化,我个人觉得比较好像也好记
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
if not nums:
return [-1, -1]
n = len(nums)
pos = -1
l, r = 0, n - 1
while l <= r:
mid = (l + r) // 2
if target == nums[mid]:
pos = mid
break
if target > nums[mid]:
l = mid + 1
else:
r = mid - 1
pos_r = pos
while pos_r + 1 < n and nums[pos_r + 1] == target:
pos_r += 1
pos_l = pos
while pos_l - 1 >= 0 and nums[pos_l - 1] == target:
pos_l -= 1
return [pos_l, pos_r]
2.官方题解:感觉不好记
class Solution:
def binarySearch(self, nums, target, lower_flag):
# 把ans赋值为len(nums)对应后续的r < n的判断命令,用于筛选没有找到target的结果
l, r, ans = 0, len(nums) - 1, len(nums)
while l <= r:
mid = l + (r - l) // 2
if target < nums[mid] or (lower_flag and target == nums[mid]):
r = mid - 1
ans = mid
else:
l = mid + 1
return ans
def searchRange(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
#lower_flag == True时,代码逻辑会在==target的元素中滑动到最左端
l = self.binarySearch(nums, target, True)
# lower_flag == False时,代码逻辑在元素小于target的时候往大找,直到找到最小的>target的元素,所以要返回后-1才能用
r = self.binarySearch(nums, target, False) - 1
if l <= r and r < n and nums[l] == target and nums[r] == target:
return [l, r]
else:
return [-1, -1]