二分查找及其Python实现【算法图解】

1. 引出问题

做一个游戏,我随便想一个整数数字,这个数字在【1-100】范围内,你的目标是以最少的次数猜到这个数字,你会怎么做?

注意:在你每次猜测后,我都会提示猜大了(猜小了/猜对了)

2. 简单查找

简单查找的过程看起来很笨,类似于这样(假设我想的数字是68):

你:1
我:猜小了
你:2
我:猜小了
你:3
我:猜小了

你:60
我:猜小了
你:woc,我不猜了,难受!!!
我:嘻嘻

显然,简单查找每次只能排除一个数字,如果我想的数字是100,你必须猜测100次才可以猜到。

3. 二分查找(折半查找)

二分查找的过程简单多了,类似于这样(假设我想的数字是68):

你:floor((100+1)/2)=50
我:猜小了
(排除了【1-50】的数字,还剩下【51-100】)
你:floor((51+100)/2)=75
我:猜大了
(排除了【75-100】,还剩下【51-74】)
你:floor((51+74)/2)=62
我:猜小了
(排除了【51-62】,还剩下【63-74】)
你:floor((63+74)/2)=68
我:猜对了!

你每次猜测都会排除约一半的数字,迅速把范围缩小,因此只用了4步就猜对了!!!

这就是二分查找,在本游戏中,每次猜测剩余的的数字个数如下:

在这里插入图片描述
在最坏情况下,我们只需要需要猜测7次就可以得到结果(而简单查找需要100次)。

4. 运行时间对比

简单查找二分查找
100个元素:最多猜测100次100个元素:最多猜测7次
4000000000个元素:最多猜测4000000000次4000000000个元素:最多猜测32次
n个元素:运行时间(猜测次数)O(n)n个元素:运行时间(猜测次数)O(log n)

可以看到,简单查找的时间是线性时间,而二分查找的时间是对数时间(底数为2),随着元素数量增加,二分查找优势愈加明显。

准确来讲,二分查找的猜测次数是ceil(log n),当有100个元素时,ceil(log 100)=7,这里用大O表示法忽略了小数

5. 二分查找的Python实现

键入以下代码并运行:

## 二分查找的函数binarySearch
## 输入:
##      orderedList:有序的列表
##      item:需要寻找的值
## 输出:
##      mid:列表orderedList中等于item的元素对应的位置索引
##      None:如果不存在与item相等的元素,返回空
def binarySearch(orderedList,item):
    low=0 # low:存储剩余范围的最小索引(下边界)
    high=len(orderedList)-1 # high:存储剩余范围的最大索引(上边界)

    while low<=high:
        mid=int((low+high)/2) # mid:计算剩余范围的中间索引
        guess=orderedList[mid] # guess:剩余范围的中间值即为猜测的数值
        if guess==item: # 如果猜对了,那么返回索引
            return mid
        if guess>item:  #  如果猜的值大了,那么将剩余范围的上边界更新为中间位置
            high=mid-1 
        else:           # 如果猜的值小了,那么将剩余范围的下边界更新为中间位置
            low=mid+1 
    return None # 如果不存在对应值,返回空

## 测试用例,第一个3存在,结果应该为1,第二个-1不存在,结果为None
myList=[1,3,5,7,9]

print(binarySearch(myList,3))
print(binarySearch(myList,-1))

这里面的注释是比较清楚的,因此就不再过多赘述,运行结果如下:
在这里插入图片描述

6. 总结

  1. 二分查找的速度比简单查找快得多。

  2. O(log n)比O(n)快,且随着元素规模的增加,前者比后者快得多。

  3. 注意:二分查找的基础是有序列表,因此无序列表不能应用二分查找。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值