之前分析了好多排序算法,可难理解了呢!!(泣不成声) 这次我要把二分查找总结一下,这个算法不算难度特别大,欢迎大家参考借鉴 我不喜欢太官方的定义,太晦涩的语言,让人看了就头晕。我希望加入我自己的理解,能帮助大家更好的理解算法的原理 同时也欢迎大家批评指正 二分查找: 我们手里有一个长度为n的正序数列,当我们想查找一个数 x是否在这个数列当中的时候 1 取数列正中间的数mid, 如果mid和x相等,则找到结果,查找成功 返回True 如果mid比x大,则x应该在mid的左侧,我们把mid左侧当作一个新的数列li 如果mid比x小,则x应该在mid的右侧,我们把mid右侧当作一个新的数列li 2 对于新的数列li 进行1的查找工作 3 一直重复上面查找,生成新的数列li为空的时候则 数列当中没有数x 返回False 时间复杂度:最优O(1) 我们取第一次中间数mid 找到了 这种概率很低 最坏O(log n) 假设n个数的数列,每次把数列分成两半,n除以多少次2 等于1 呢? log n次 首先我们用递归的方式实现二分查找算法:
1 #递归实现二分查找 li是列表 item是要查找的元素 2 def merge_search( li ,item ): 3 #传来的列表每次都是新生成的,如果发现里面没有元素,则是查找到尽头都没找到 4 if not li : 5 return False 6 7 mid = len(li)//2 #mid记录li的中间位置 8 #检查一下 如果中间这个数就是要找的元素 返回真 9 if li[mid] == item :10 return True11 # 如果mid比item大,说明item可能会出现在mid左边,对左边再查找12 elif li[mid]> item :13 return merge_search( li[:mid] ,item )14 # mid 比item小,说明item有可能在mid右边,对右边再查找15 else :16 return merge_search( li[mid+1:] , item )17 18 if __name__ == '__main__':19 li = [1,2,3,4,5,6,7]20 print( merge_search(li , 0) ) #False21 print( merge_search(li , 1) ) #True
下面我们尝试用while循环去实现二分查找:
1 def merge_search( li , item ): 2 #获取li的开始 结束 3 start = 0 4 end = len(li)-1 5 6 #只要start和end 还没错开 就一直找 7 while start <= end : 8 #通过计算获取当前查找范围的中间位置 9 mid = (start + end)//210 #如果中间数就是item则返回True11 if li[mid] == item :12 return True13 #如果mid比item大,说明item可能会出现在mid左边,对左边再查找14 elif li[mid]> item :15 end = mid - 116 # mid 比item小,说明item有可能在mid右边,对右边再查找17 else :18 start = mid + 119 #跳出循环说明没找到 返回错误20 return False21 22 if __name__ == '__main__':23 li = [1,2,3,4,5,6,7,8]24 print( merge_search(li , 8) ) #True25 print( merge_search(li , 0) ) #False
OK 以上就是两种实现二分查找的方法。
因为思想相同,他们的时间复杂度是一样的。
但是递归的方式,每次都要开新的列表,实际上空间复杂度会更大一些。
谢谢你的观赏~欢迎大家批评指正!