二分法基本代码
#bi-search
data = [1,2,3,3, 3, 4,5,6]
#lower_bound
# >= x 的第一个数字
def lower_bound(data, l , r, x):
while (l < r):
m = int((l + r) / 2)
if data[m] < x:
l = m + 1
else:
r = m
return l
#upper_bound
# > x 的第一个数字
def upper_bound(data, l, r, x):
while (l < r):
m = int((l + r) / 2)
if (data[m] <= x):
l = m + 1
else:
r = m
return l
二分法解决实际的问题
e.g. 给定一个数组,data = [1,2,3,4,5,2,1,2,64,3]
, 寻找一个最小的划分size,将数据划分为m组。
对于这种问题,往往需要寻找一种映射,寻找出问题中的单调性。
#二分法 搜索。
data = [1,2,3,3,2,1,5,7]
m = 5
#将data 划分为 m组,每组的最大的sum,尽可能小。
#可以划分的方案为[0, sum(data)],且如果以 x 划分可行,那么 [x ~ sum(data)]的划分也可行。即在区间上面有单调性。
def validate(data, div_size):
grop = 0
sum = 0
for n in data:
if (sum + n < div_size):
sum += n
else:
grop += 1
sum = n
return grop <= m
[validate(data, i) for i in range(sum(data))]
# [False,False,False,False,False,False,False,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True]
# 可以看到具有单调性, 故使用二分法进行寻找最小的划分SIze
l = 0
r = sum(data)
while l < r:
mid = int((l + r) / 2)
if (validate(data, mid)):
r = mid
else:
l = mid + 1
print("最小需要的划分size 为{} ".format(l))