线性查找
🥱
def LinearSearch(A, value):
for idx in range(len(A)):
if A[idx] == value:
return idx
return None
二分查找
迭代形式
🥱看似平平无奇
def BinarySearchIterative(A, value):
low, high = 0, len(A)-1
while low <= high:
mid = (low + high) // 2
if A[mid] > value:
high = mid - 1
elif A[mid] < value:
low = mid + 1
else:
return mid
return None
实际上这段代码有 bug ?看出来了吗!估计你是看不出来的 🙃
跑个测试例子:
A = [534, 246, 933, 127, 277]
for i in A:
print(BinarySearchIterative(A, i))
'''
0
None
2
None
None
'''
5 个数有 3 个找不到,真是奇耻大辱 😅
问题出在哪呢?
问题出在你输入的数组没排序 😅
所以函数其实没问题 😅
啰嗦一堆就是想强调一下二分查找只能用于排好序的数组 😅
递归形式
def BinarySearchRecursive(A, value, low_high=None):
if low_high is None:
low, high = 0, len(A)
else:
low, high = low_high
if low > high or len(A) == 0:
return None
mid = low + (high - low) // 2
if A[mid] > value:
return BinarySearchRecursive(A, value, (low, mid-1))
elif A[mid] < value:
return BinarySearchRecursive(A, value, (mid+1, high))
else:
return mid
插值查找
假设数组中的数据分布是均匀的,那就可以通过元素值的大小预判查找的位置是在数组的前半段还是后半段,而不必死板地从中间位置开始找
比如你要从英汉词典中找 apple 这个单词,你肯定不会从词典中间开始找,而是直接锁定词典的前几页或前八分之一
def InterpolationSearch(A, value):
low = 0
high = len(A) - 1
while A[low] < value and A[high] >= value:
mid = low + int((value - A[low]) / (A[high] - A[low]) * (high - low))
if A[mid] < value:
low = mid + 1
elif A[mid] > value:
high = mid - 1
else:
return mid
if A[low] == value:
return low
return None
插值查找与二分查找的效率对比
代码计时:python 代码计时
import time
class Timer(object):
def __enter__(self):
self.t0 = time.time()
def __exit__(self, exc_type, exc_val, exc_tb):
print('[time spent: {time:.2f}s]'.format(time = time.time() - self.t0))
对千万数据进行逐个查找:
A = [i for i in range(10000000)]
with Timer():
for i in A:
InterpolationSearch(A, i)
# [time spent: 5.57s]
with Timer():
for i in A:
BinarySearchIterative(A, i)
# [time spent: 29.61s]
二分查找花了 30 秒, 而插值查找仅用了 6 秒 !!
事实上,插值查找的平均时间复杂度为 O ( log ( log n ) ) O(\log(\log n)) O(log(logn))
常见考题
1. 判断数组中是否有重复元素
解法 | 时间 | 空间 |
---|---|---|
两重循环 | n 2 n^2 n2 | 1 |
先排序,再遍历 | n log n n\log n nlogn | 1 |
哈希表 | n | n |