1. 题目
题目描述:
给定一个按照非递减顺序排列的整数数组 nums
,和一个目标值 target
。请找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值,返回 [-1, -1]
。
要求:
必须使用二分查找算法
时间复杂度必须是 O(log n)
不能使用线性扫描或内置函数直接查找(如
index()
、find()
等)
示例:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
输入: nums = [], target = 0
输出: [-1,-1]
2. 思路
1. 为什么必须用二分查找
题目明确要求时间复杂度 O(log n)
线性扫描法(O(n))不符合要求
数组已排序,是二分查找的典型应用场景
2. 问题分解
需要解决两个子问题:
找到
target
的第一个位置(左边界)找到
target
的最后一个位置(右边界)
3. 二分查找变种
标准二分查找找到目标值就返回
本题需要继续查找边界,因此需要修改标准算法
4. 算法步骤
实现查找左边界的二分查找
当
nums[mid] >= target
时继续向左搜索最后检查找到的位置是否等于
target
实现查找右边界的二分查找
当
nums[mid] <= target
时继续向右搜索最后检查找到的位置是否等于
target
组合两个结果
3. 代码
nums=list(map(int,input().split()))
target=int(input())
"""
在排序数组中查找元素的第一个和最后一个位置
param nums: 非递减排序的整数数组
param target: 要查找的目标值
return: 目标值的起始和结束位置 [start, end],如果不存在返回 [-1, -1]
"""
def find_left():
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] >= target:
right = mid - 1
else:
left = mid + 1
return left if left < len(nums) and nums[left] == target else -1
def find_right():
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] <= target:
left = mid + 1
else:
right = mid - 1
return right if right >= 0 and nums[right] == target else -1
if not nums:
return [-1, -1]
left_pos = find_left()
right_pos = find_right()
print([left_pos, right_pos])