算法初步:二分查找
Posted 芒果编程工作室
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法初步:二分查找相关的知识,希望对你有一定的参考价值。
问题:
给你一串排好序(升序)的数字和一个目标数字,如何找到该目标数字在这串数字中的第几位?(假设目标数字一定在这串数字中,而且没有重复的数字)
算法1:
第一种方法,大家肯定想到了暴力解法,从第一位开始找,直到最后一个数字,找到了就直接返回。
这种算法的时间复杂度是O(n),属于线性级的复杂度,即数列的长度是多少,就要比对多少次,还能接受。
代码实现:
#!/usr/bin/python3
nums_str = input("请输入排序好的数列(以英文逗号隔开):")
target_num = int(input("请输入目标值:"))
nums_list = nums_str.split(',')
target_pos = 0
#从头开始找
for i in range(0, len(nums_list)):
if int(nums_list[i]) == target_num:
target_pos = i
break
print("目标值在数列中的第%d位置" % (target_pos + 1))
执行结果:
算法2:
既然这些数字都是排好序的,那是不是可以先拿这串数字中间的那个数字和目标值比较呢?
如果相等,那最好,直接就找到了;
如果目标值大于中间数,说明目标值在中间数的右边,左边数字的都可以舍弃,不用比对;
如果目标值小于中间数,说明目标值在中间数的左边,右边的数字都可以舍弃,不用再比对了。
这样一步下来,基本就可以舍弃掉一半的数字不用再比对了,而且拿到了一个更小的范围区间。接下来再在这个范围区间里,重复这样的操作,直到找到了目标值为止。
这种算法的时间复杂度是O(log(n)),属于对数级的复杂度,比第一种算法的O(n)进步了很多。
试想,如果这个数列的长度非常非常大,有一百万个数字,第一种算法就需要比对一百万次,而第二种算法只需要log₂1000000,约等于20。一个百万次比较,一个20次比较,哪个算法的效率高,应该很明了了。
这种算法,我们称之为二分查找法,也就是每一次操作后,都能舍弃掉一半的无效结果,只需要在另一半有效的结果里查找即可。
代码实现:
#!/usr/bin/python3
import math
nums_str = input("请输入排序好的数列(以英文逗号隔开):")
target_num = int(input("请输入目标值:"))
nums_list = nums_str.split(',')
# 区间左侧索引
left = 0
# 区间右侧索引
right = len(nums_list) - 1
while left < right:
print("==========本次查找的范围是:", nums_list[left:right + 1])
middle = (left + right) // 2
middle_num = int(nums_list[middle])
print("中间的数字为:%d" % middle_num)
if middle_num == target_num:
break
elif middle_num > target_num:
print("%d>%d,所以再从%d的左侧比较" % (middle_num, target_num, middle_num))
right = middle - 1
else:
print("%d<%d,所以再从%d的右侧比较" % (middle_num, target_num, middle_num))
left = middle + 1
target_pos = (left + right) // 2
print("目标值在数列中的第%d位置" % (target_pos + 1))
执行结果:
以上是关于算法初步:二分查找的主要内容,如果未能解决你的问题,请参考以下文章