二分拾遗

二分法基本代码

#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))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值