二分的细节

Posted smoncaff

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分的细节相关的知识,希望对你有一定的参考价值。

  满足单调性的情况下,可以用二分法找出答案,复杂度为logn

  1.在整数范围内,闭区间[l,r]的二分,以l==r为结束条件。边界条件需要考虑几个问题,当l或r更新的时候范围是否有缩小(若无则选入死循环),是赋得新值之后l是否==r而不是>r;

  2.根据题目设计选取mid归属于左半区间还是右半区间,假设我们要在单调递增的数组里面找第一个 >=val的值  假设a[mid]符合条件,那么可知mid的右边全都符合条件,但不知道mid的左边有没有符合条件的数字,因此在划分区间的时候不可以将mid去掉,因此r=mid,l=mid+1;为了使r=l+1的时候l<=r,此时mid=(l+r)>>1==l;

1 int binary_1(int l,int r,int val)
2 {
3     while(l<r)
4     {
5         int mid=(l+r)>>1;
6         if(a[mid]>=val)    r=mid;else l=mid+1;
7     }
8     return l;
9 }

  3.假设还是一个单调递增的数列,取第一个<=val的值,假如a[mid]符合条件,则mid的左半部分都符合条件,右半部分不一定有符合条件的,因此不能舍去,l=mid,r=mid-1;mid=(l+r+1)>>1;当r=l+1时,mid=r,为了缩小边界,r=mid-1;

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

 

    其中用位运算>>1而不是用/2 是因为在遇到负数的时候>>1是向下取整, /2是向0取整

  4.可以把[1,n]扩大为[0,n] [1,n+1],当去到r取0,或者l取n+1的时候即无解

 

  5.在实数域上的二分只需要考虑精度,则确定精确度即可,抑或是二分固定次数

  

 1 double binary(double l,double r,double exp)
 2 {
 3     while(r-l>exp)
 4     {
 5         double mid=(l+r)/2;
 6         if(cal(mid)) l=mid;else r=mid;
 7     }
 8     
 9     for(int i=1;i<=100;i++)
10     {
11         double mid=(l+r)/2;
12         if(cal(mid))l=mid;else r=mid;
13     }
14 }

 

  6.当l+r很大的时候有可能溢出,更妥当的写法是 l+(r-l)>>1     /    l+(r-l)>>1+1;

  7.三分法求极值(单峰函数严格单调) 将区间三分,比较mid1和 mid2 极值点一定不在某个区间上,此区间为[l,mid1]或[mid2,r] 

  

double maxx(double l,double r,double exp)
{
    while(r-l>exp)
    {
        double k=r-l/3,mid1=l+k,mid2=r-k;
        if(f(mid1)<f(mid2))    l=mid1;else r=mid2;
    }
    return l;
}

 

  

以上是关于二分的细节的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 创建反汇编解析器实例对象 | 设置汇编解析器显示细节 )(代码片段

二分细节处理(没有任何人去关注,但是确实让我很伤脑,处理不好会死人吧!)

[算法分析]二分查找细节分析与技术要点

二分查找+所有细节保姆级详解

图解 | 二分查找法需要注意的那些细节

"细节魔鬼" - 二分查找