二分查找问题查找元素和查找左右边界

Posted 生物信息与python

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分查找问题查找元素和查找左右边界相关的知识,希望对你有一定的参考价值。

二分查找从整体逻辑上来讲并不难,它的难度在于细节问题。下面给出常用套路:

首先判断问题的类型:如果是求值问题,则right=len(seq)-1(左右都是闭区间[left, right]),如果是求边界问题,则right=len(seq)(左闭右开区间[left, right)),然后如果是左右均为闭区间,则while left <= right,如果左闭右开区间,则while left < right。(关于while这里就这样判断,做题肯定没有问题),下面我们来看三个具体问题。


  1. 二分查找求列表中是否存在某个数。

这个没有难度, 主要是两处细节问题。当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 leftif __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


以上是关于二分查找问题查找元素和查找左右边界的主要内容,如果未能解决你的问题,请参考以下文章

二分查找算法

二分查找边界控制

二分查找边界控制

二分查找及其应用总结

二分查找,边界思维的惊险挑战

递归 —— 二分查找法 —— 归并排序