数据结构与算法:二分算法

Ⅰ.二分算法:

二分算法是非常精妙的算法,可以将许许多多问题转化为判定的问题。二分的应用范围十分广泛,并不仅仅应用在单调区间上查找数值。而且二分算法经常与离散化配套使用,是居家旅行必备的算法。什么时候可以对问题进行二分?二分的本质并不是单调性,而是我们通过某种判定,使得区间的前半部全部满足而后半部分全部不满足,此时就可以二分了。

二分算法虽然有模板且代码量短,但是许多细节需要注意,非常容易陷入死循环或者数组越界的麻烦(整数域的二分)。我们最好深刻理解,我们通过二分最后得出的位置究竟是代表什么意义(本人也得好好地累积经验深刻理解,还是太菜了)

 

Ⅱ.整数域的二分算法模板:

一、模板1

代码

模板1:
//l, r 初始化成取值范围的左右边界
while( l < r ){
    int mid = l + r >> 1;
    if( check(mid) ) r = mid;
    else l = mid + 1;
} 
//二分结束后,l==r,l,r都是最终的答案


个人理解:(图 + 文)

如上图(模板1)。x代表的是满足判定的第一个点的位置。

①若 mid >= x ,则说明答案必在mid的左边(包含mid),也就是答案会落在 [ l , mid ] 区间内。此时更新:r = mid 即可。

②否则 mid < x ,则说明答案严格在mid的右边,答案会落在 [ mid + 1,  r ] 区间内。此时更新: l = mid + 1 即可。

 

二、模板2

代码

while( l < r ){
    int mid = l + r + 1 >> 1;
    if( check(mid) ) l = mid;
    else r = mid - 1; 
}

个人理解

如上图(模板2):x代表满足判定的最后一个点的位置。

①若 mid <= x ,则说明答案必在mid的右边(包含mid),也就是答案会落在 [ mid , r ] 区间内。此时更新:l = mid 即可。

②否则 mid > x ,则说明答案严格在mid的左边(不包含mid),答案会落在 [ l,  mid - 1 ] 区间内。此时更新: r = mid - 1 即可。 

三、总结:

相信你已经发现,模板一和模板二的差异主要集中在 l 和 r 的更新方式上,更新方式的判断如上文所述就可以了。还有 mid 的取值的不同,mid 的取值是有规律的,这里直接摆出规律作为参考:

当更新方式为 r = mid 的时候, mid 的取值是 mid = l + r >> 1 。

当更新方式为 l = mid 的时候, mid 的取值是 mid = l + r + 1 >> 1 。 

当然了,二分算法的写法各式各样。适合自己的,并且自己理解不会出错的才是最好的。

Ⅲ.实数域上的二分

实数域上的二分就比整数域的二分简单多了。因为不涉及左右区间的取舍或者边界问题。注意所需要的精度即可。这里直接甩模板:

double esp = 1e-6;//esp是精度,精度越高越逼近答案。
while( l + esp < r ){
    double mid = ( l + r )/2;
    if( cal(mid) ) r = mid;
    else l = mid;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值