二分的细节
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 文件中的机器码数据 | 创建反汇编解析器实例对象 | 设置汇编解析器显示细节 )(代码片段