该文章的很多思想来自《算法图解》(著:Aditya Bhargava,译:袁国忠)
定义
二分法(Bisection method) 即一分为二的方法. 设[a,b]为R的闭区间. 逐次二分法就是造出如下的区间序列([an,bn]):a0=a,b0=b,且对任一自然数n,[an+1,bn+1]或者等于[an,cn],或者等于[cn,bn],其中cn表示[an,bn]的中点.
算法思想
当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的,假设数据是按升序排序的。
基本思想如下:
对于给定值key,从序列的中间位置
m
i
d
mid
mid开始比较,
l
o
w
low
low为初始位置,
h
i
g
h
high
high为末尾位置,
如果当前位置
a
r
r
[
m
i
d
]
arr[mid]
arr[mid]值等于
k
e
y
key
key,则查找成功;
若
k
e
y
key
key小于当前位置值
a
r
r
[
m
i
d
]
arr[mid]
arr[mid],则在数列的前半段中查找,
a
r
r
[
l
o
w
,
m
i
d
−
1
]
arr[low,mid-1]
arr[low,mid−1];
若
k
e
y
key
key大于当前位置值
a
r
r
[
m
i
d
]
arr[mid]
arr[mid],则在数列的后半段中继续查找
a
r
r
[
m
i
d
+
1
,
h
i
g
h
]
arr[mid+1,high]
arr[mid+1,high],
直到找到为止。
二分法的时间复杂度为:
O
(
log
2
(
n
)
)
O(\log_2(n))
O(log2(n)),
n
n
n为序列长度。
举例如下
对于[1, 100]这100个数字组成的序列中,找到数字15所在的位置,那么利用二分法图例如下:
![](https://i-blog.csdnimg.cn/blog_migrate/b47fc7de39f621fec1eab4bf0fb6c3dc.jpeg)
这样我们利用了5步就找到目标值15的位置。二分法的时间复杂度为: O ( log 2 ( n ) ) O(\log_2(n)) O(log2(n)),普通枚举法的时间复杂度为: O ( n ) O(n) O(n),其中 n n n为序列长度。由此可以看出,数据量越大,二分法的优势就越明显。
编码实现
# 注意这里的pre_list必须是有序的
def binary_search(pre_list, target):
low = 0
mid = None
high = len(pre_list) - 1
# 如果目标值越界,则直接返回 None
if target < pre_list[low] or target > pre_list[high]:
return mid
# 如果目标值在范围内,再进行处理
while low <= high:
mid = int(low / 2 + high / 2)
if target == pre_list[mid]:
break
elif target < pre_list[mid]:
high = mid - 1
else:
low = mid + 1
return mid