二分查找问题查找元素和查找左右边界
Posted 生物信息与python
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分查找问题查找元素和查找左右边界相关的知识,希望对你有一定的参考价值。
二分查找从整体逻辑上来讲并不难,它的难度在于细节问题。下面给出常用套路:
首先判断问题的类型:如果是求值问题,则right=len(seq)-1(左右都是闭区间[left, right]),如果是求边界问题,则right=len(seq)(左闭右开区间[left, right)),然后如果是左右均为闭区间,则while left <= right,如果左闭右开区间,则while left < right。(关于while这里就这样判断,做题肯定没有问题),下面我们来看三个具体问题。
二分查找求列表中是否存在某个数。
这个没有难度, 主要是两处细节问题。当seq[mid] == num:时,直接返回值
def binarySearch(seq: list, num: int):
left, right = 0, len(seq) - 1
while left <= right:
mid = int(left + (right - left) / 2)
if seq[mid] == num:
return mid
elif seq[mid] > num:
right = mid - 1
elif seq[mid] < num:
left = mid + 1
2.求在一个有序序列中小于指定元素的元素个数(或者说是某个指定元素在该列表中下标最小值),比如列表为[1, 1, 2, 2, 5],给指定元素为2,则函数返回指定元素对应下标的最小值为2,正好是小于它的元素个数。
细节问题主要是两个。一是当seq[mid] == num时,此时需要缩小范围,所以right = mid,之所以是等于mid而不是等于mid-1的原因在于右侧是开区间,如果等于mid-1的话,相当于[left, mid-1),这个时候mid-1这个下标对应的元素值就取不到了。在seq[mid] > num时是同理。二是最后返回的是left。在二分查找中查找到最后一定是left=right,所以此处返回left,或者返回right都可以。
def leftBinarySearch(seq: list, num: int):
left, right = 0, len(seq)
while left < right:
mid = left + (right - left) // 2
if seq[mid] == num:
right = mid
elif seq[mid] < num:
left = mid + 1
elif seq[mid] > num:
right = mid
return left
if __name__ == '__main__':
print(leftBinarySearch([1, 1, 2, 2, 5], 2))
######
2
3. 求在一个有序序列中某个指定元素在该列表中下标最大值),比如列表为[1, 1, 2, 2, 5],给指定元素为2,则函数返回指定元素对应下标的最大值为3。
细节问题也是两个,一是seq[mid] == num时,为缩小范围,mid=mid+1,这里的原因很简单,还是由于左闭右开区间所以左边为mid+1,如果为mid的话,相当于是[mid,right),显然错误。二是最后返回的是left-1,原因是left = mid +1,也就是说mid= left -1,最后实际上是输出mid的位置。
def rightBinarySearch(seq: list, num: int):
left, right = 0, len(seq)
while left < right:
mid = left + (right - left) // 2
if seq[mid] == num:
left = mid + 1
elif seq[mid] < num:
left = mid + 1
elif seq[mid] > num:
right = mid
return left -1
if __name__ == '__main__':
print(rightBinarySearch([1, 1, 2, 2, 5], 2))
#######
3
以上是关于二分查找问题查找元素和查找左右边界的主要内容,如果未能解决你的问题,请参考以下文章