二分查找算法,你真的了解吗?
输入是一个有序的元素列表
如果要查找的元素包含在列表中,二分查找返回其位置;否则返回null。
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
摘自百度百科
运行结果:
I
while循环的终止条件low<high还是low<=high?
当数组只有一个元素时,此时low=high,使用low<high作为循环终止条件会漏掉这一个元素!
II
mid=(low+high)/2时会存在溢出。
计算机在进行计算时,会先计算low+high的值,16位的整型数字最大为65535,假设此时low=30000,high=40000,二者的和为70000,超过整型最大值,产生溢出!
使用mid=low+(high-low)/2可解决溢出问题!
Python3.x版本中执行的是“真”除法,会导致float代替整数,所以会出现如下错误:
TypeError: list indices must be integers or slices, not float
所以在Python3.x版本中可表示为
(low+high)//2
算法时间复杂度为O(logn) 底数为2
假设要画一个网格,包含16个格子
方法一:
每次画一个的方式画16个格子,需要操作16次
运行时间是O(n)
方法二:
将纸折起来
对折一次就是一次操作,第一次对折相当于画了两个格子!
折四次即可获得16个网格!
运行时间是O(logn)
算法运行时间并不以秒为单位,从其增速的角度度量!
算法的速度指的并非是时间,而是操作数的增速。
谈论算法的速度时,我们说的是随着输入的增加,其运行时间将以什么样的速度增加。
摘自书籍《算法图解》
有时候有序数组并不是完全顺序排列的,例如[1,2,3,3,5,9],这个时候使用二分查找并不能完全满足查找需求。
例如我想查找第一个数字3的索引2,表示比3小的数字有2个。结果查找到的是第二个数字3的索引3,这就牵扯到寻找左右边界的二分查找了!