二分查找的变形
作用:将查找的时间复杂度由o(n) 变为o(logn)
给定一个按照升序排列的整数数组 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
https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
# 找左边 左闭右开区间
def findleft(fir,end):
while (fir<end):
mid = fir +(end-fir)//2
if (nums[mid]==target):
end = mid
elif (nums[mid]>target):
end = mid
elif (nums[mid]<target):
fir = mid+1
if (fir>=len(nums)):
return -1
return fir if nums[fir]==target else -1
为什么循环的判断条件为fir<end
本函数查找到范围是[fir,end) 左闭右开区间
显然例如当fir=end=3时 ,此时区间为[3,3) 不是一个有值的区间
为什么此时让end=mid , if (nums[mid]==target): end = mid
找出给定目标值在数组中的开始位置,此时即使查到了也有可能是所有target值当中靠近中间的位置,还要继续找到最左侧,而查找范围end对应是开区间,所以还可以在[fir,mid)中查找
为什么要判断if (fir>=len(nums)):
最后target可能比数组中所有元素都大,此时应该返回查找不成功的标志-1
target如何在数组中不存在怎么办
判断最后查找出来的fir所在的值是否和target相等 return fir if nums[fir]==target else -1
查找右侧区间类似,完整代码如下
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
ans = []
if(len(nums)==0):
return [-1,-1]
# 找左边 左闭右开区间
def findleft(fir,end):
while (fir<end):
mid = fir +(end-fir)//2
if (nums[mid]==target):
end = mid
elif (nums[mid]>target):
end = mid
elif (nums[mid]<target):
fir = mid+1
if (fir>=len(nums)):
return -1
return fir if nums[fir]==target else -1
ans.append(findleft(0,len(nums)))
def findright(fir,end):
while (fir<end):
mid = fir+(end-fir)//2
if(nums[mid]==target):
fir = mid+1
elif (nums[mid]>target):
end = mid
elif (nums[mid]<target):
fir = mid+1
return fir-1 if nums[fir-1]==target else -1
ans.append(findright(0,len(nums)))
return ans