读算法图解笔记一(二分查找)
二分查找
二分查找是一种算法,其输入时一个有序的元素列表(元素必须是按照顺序排列的)。如果要查找的元素包含在列表中,二分查找返回其位置;否则返回null
仅当列表是有序的时候,二分查找才管用。例如,电话簿中的名字是按照字母排列的,因此可以使用二分查找来查找名字。如果名字不是按顺序排列的,就无法使用二分查找来查找了。
例如:随机想一个1-100的数字,目标是以最少的次数猜到这个数字,每次猜测后,会提示猜小了、猜大了或者猜对了
1、假如从1开始依次往后猜,这就是简单查找,更准确的说法是傻找,每次猜测都只能排除一个数字。如果想的数字是99,那么得猜99次才能猜对。
2、更佳的猜法,是从50开始,提示小了,但是排除了一半的数字,至此,你知道1-50都小了,接下来,你猜51-100之间的数字75,提示大了,那么余下的数字又排除了一半!使用二分查找时,你猜测的是中间的数字,从而每次都将余下的数字排除了一半。
这就是二分查找,每次猜测排除的数字个数如下:
100个元素-->50-->25-->13-->7-->4-->2-->1 //7步,使用二分查找时,每次都排除一半的数字
不管心里想的是哪个数字,你在7次之内都能猜到,因为每次猜测都将排除很多数字!
3、简单查找、二分查找时分别使用的步数
一般而言,对于包含n个元素的列表,用二分查找最多需要log(2)(n)步,而简单查找最多需要n步。
//补充对数知识 你可能不记得什么是对数了,但很可能记得什么是幂。log(10)(100)相当于“将多少个10相乘结果为100”.答案是两个:10 x 10=100。因此,log(10)(100)=2。对数运算时幂运算的逆运算。 2的三次方=8 <--->log(2)(8)=3 2的四次方=16 <--->log(2)(16)=4 后期,log指的都是log(2)
使用简单查找法查找元素时,在最糟糕的情况下需要查看每个元素。因此,如果列表中有8个数字,你最多需要检查8个数字。
而使用二分查找时,最多需要检查log n个元素。如果列表中包含8个元素,你最多需要检查3个元素,因为log 8=3 (2的三次方等于8),如果列表中包含1024个元素,你最多需要检查10个元素,因为log 1024=10(2的10次方等于1024)
例如:使用python来执行二分查找数组元素(数组从0开始编号)
函数binary_search接受一个有序数组和一个元素。如果指定的元素包含在数组中,这个函数返回其位置。
def binary_search(list,item) //函数binary_search代表输入一个有序数组,item为查找的元素
数组
Low High
... | .. | ... | ... | ... |
Low=0
High=len(list)-1
每次都检查中间的元素
mid=(Low+High)/2 //如果(Low+High)不是偶数,Python自动将mid向下取整
guess=list[mid]
如果猜的数字小了,就相应地修改Low。
if guess<item Low=mid+1
mid Low的新值 High
... | ... | ... | ... | ... |
如果才的数字大了,就修改High
if guess>item High=mid-1
Low High的新值 mid
... | ... | ... | ... | ... |
完整的代码如下:
def binary_search(list,item): Low=0 High=len(list)-1 while low<=High: mid=(Low+High)/2 guess=list[mid] if guess==item: return mid if guess>item: High=mid-1 else: Low=mid-1 return None
测试一下:
my_list=[1,3,5,7,9]
print binary_search(my_list,3) #--》1,索引从0开始,第二个位置的索引为1 print binary_search(my_list,-1) #--》None,在Python中,None表示为空,它意味着没有找到制定的元素