0x04 二分

0x04 二分

二分是一种随处可见却非常精妙的算法。二分得基础用法是在单调序列或单调函数中进行查找。因此当问题的答案具有单调性时,就可以通过二分将求解转化成判定(根据复杂度理论判定难度小于求解),这使得二分应用的范围十分广泛。进一步的,我们还可以扩展到通过三分法去解决单峰函数的极值以及相关问题。

1.整数集合上的二分

借助二分,我们把求最优解的问题,转化为给定一个值mid,判断是否存在一个可行方案评分达到mid的问题。

求最小值的最大情况

while(left<=right)
{
    int middle=(right+left)/2;
    if(check(middle))
    {
        ans=middle;
        left=middle+1;
    }
    else
        right=middle-1;
}

求最大值的最小情况

while(left<=right)
{
    int middle=(right+left)/2;
    if(check(middle))
    {
        ans=middle;
        right=middle-1;   
    }
    else
        left=middle+1;
}

2.实数域上的二分

实数域上的二分比较简单,确定好精度 e p s eps eps,以 l + e p s < r l+eps<r l+eps<r 为循环条件,每次根据在mid上的判定选择l=mid或r=mid分支之一即可。一般需要保留k位小数,则取 e p s = 1 0 − ( k + 2 ) eps=10^{-(k+2)} eps=10(k+2)

while(right-left>eps)  //答案所需的精度eps
{
    double middle=(l+r)/2;
    if(check(middle)) right=middle;
    else left=middle;
}

3.三分求单峰函数极值

有一类函数被称为单峰函数,它们拥有唯一的极大值点或者唯一的极小值点。

以拥有唯一极大值点的单峰函数f为例,我们在定义域[l,r]内任取两个点 l m i d lmid lmid r m i d rmid rmid,把函数分为三段。

1.若 f ( l m i d ) < f ( r m i d ) f(lmid)<f(rmid) f(lmid)<f(rmid),则 l m i d lmid lmid r m i d rmid rmid要么同时位于极值点左侧,要么位于极值点两侧。无论哪种情况极值点都在 l m i d lmid lmid右侧,可令 l = l m i d l=lmid l=lmid

2.同理,若 f ( l m i d ) > f ( r m i d ) f(lmid)>f(rmid) f(lmid)>f(rmid),极大值点一定位于 r m i d rmid rmid左侧,可令 r = r m i d r=rmid r=rmid

如果我们取 l m i d lmid lmid r m i d rmid rmid为三等分点,那么定义域每次缩小1/3。如果我们取 l m i d lmid lmid r m i d rmid rmid在二等分点两侧及其接近的地方,那么定义域范围每次近似缩小1/2。通过log级别的时间复杂度即可在指定精度下求出极值。这就是三分法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谷神星ceres

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值