二分总结

虽然二分是一个很基础的算法,可是其重要性是十分显然的

二分的思想也可以扩展到许多更高级的算法和数据结构上

所以有必要学好二分的本质和精髓,掌握二分的许多细节

我们先来看一个最最基本的例子:

给一个排好序的长为n的序列

求出大于等于k的第一个位置

很显然,我们并不需要一个一个查找,我们假设要求的位置在区间[L,R]中

取中点mid,若中点处的值大于或等于k,那么答案一定[L,mid]这个区间内

注意到mid是有可能成为答案的,所以划分区间时要注意

但如果mid处的值小于k,那么mid一定不会成为答案,所以答案区间在[mid+1,R]中

在划分区间时,我们发现有[L,mid]这个区间,所以mid的值不能与R相等,不然可能死循环

所以我们去mid时要向下取整,避免这种现象

    while(r>l)
    {
        int mid=l+r>>1;
        if(a[mid]>=k) r=mid;
        else l=mid+1;
    }

将问题转换一下

给一个排好序的长为n的序列

求出小于等于k的第一个位置

这与上面的问题其实也是类似的

将区间划分为[L,mid],[mid+1,R]两个部分

只不过当a[mid]小于等于k时,可能的答案区间为[mid,R]

而当a[mid]大于k时可能的答案区间为[L,mid-1]

这样的话为了避免死循环,我们就得将mid向上取整

即mid=(l+r+1)/2;

    while(r>l)
    {
        int mid=(l+r+1)>>1;
        if(a[mid]<=k) l=mid;
        else r=mid-1;
    }

我们来深入研究二分的本质,发现二分降低复杂度的根本原因其实是因为答案的单调性

那么,其实所有具有单调性的答案其实都是可以通过二分来查找的

我们也称答案具有二分性

对于具有二分性的答案,往往在有求满足条件最小或最大的值时,就可以利用二分来求解了

posted @ 2018-07-15 19:12  logeadd  阅读(199)  评论(0编辑  收藏  举报