前言:查找可以说是我们代码里用得比较多的操作,比如我们经常需要在一个列表里找到我们需要的一个元素,然后返回它的位置。 其实哈希表就是非常高效率的查找数据结构,很明显地它是用空间换时间。这一节介绍两个基本的基于线性结构的查找。
不过在讲二分查找之前,我们先谈谈算法的时间复杂度和空间复杂度
1)时间复杂度是用来估计算法运行时间的一个式子(单位)。
2)常见的时间复杂度(按效率排序)
O(1)
3)如何一眼判断时间复杂度?
空间复杂度:用来评估算法内存占用大小的一个式子
“空间换时间”
列表查找:从列表中查找指定元素
其中这里介绍的列表查找方法有线性查找和二分查找
线性查找就是从头找到尾,直到符合条件了就返回。比如在一个 list 中找到一个等于 5 的元素并返回下标:
number_list = [0, 1, 2, 3, 4, 5, 6, 7]
def linear_search(value, iterable):
for index, val in enumerate(iterable):
if val == value:
return index
return -1
assert linear_search(5, number_list) == 5
上一小节说的线性查找针对的是无序序列,假如一个序列已经有序了呢,我们还需要从头找到尾吗?当然不用,折半(二分)是一种经典思想。
从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。
思路:
def binary_search(sorted_array, val):
if not sorted_array:
return -1
low = 0
high = len(sorted_array) - 1
while low <= high:
mid = int((low + high) / 2) # 为了屏蔽 python 2/3 差异我用了强转
#mid = (low+high)//2 或者使用这种方式,也是可行的
if sorted_array[mid] == val:
return mid
elif sorted_array[mid] > val:
high = mid - 1
else:
low = mid + 1
return -1 #未找到,返回为-1
def test_binary_search():
a = list(range(10))
# 正常值
assert binary_search(a, 1) == 1
assert binary_search(a, -1) == -1
# 异常值
assert binary_search(None, 1) == -1
# 边界值
assert binary_search(a, 0) == 0