每次可以说二分的边界问题都让博主非常头疼,今天仔细研究了一下,并做一下总结。

对于二分的边界问题,我们主要要抓住我们在写二分法时的实现方式。而最最重要的是要分析while()循环内条件,并据此解决l和r的边界处理问题。

NO.1 循环条件(也可以说实现方式)决定左右边界的取值

常见好用的方法一共有两种:

循环条件一:while(l<=r),利用ans=mid记录下答案

这时代码中相应的ans=mid,l=mid+1,r=mid-1,具体见下面代码

while (l<=r)//显然,循环跳出的条件是l>r,那么l,r都不是我们要的答案,所以用一个ans记录
{
int mid=(l+r)/2;
if (check(mid))
{
ans=mid;
r=mid-1;//记录答案后,由于r本来就不是答案,所以直接跳过mid
}
else l=mid+1;//由于r本来就不是答案,所以直接跳过mid
}
printf("%d",ans);

循环条件二:while(l<r),此时结束条件为l==r,最后l和r都是答案,输出任意其一即可

这时代码中相应的 r和l要看具体check函数所表达的具体含义,不是r=mid-1,l=mid就是l=mid+1,r=mid,总之l和r必然有一个要包含mid这个可行解,具体见下面代码

while (l<r)
{
int mid=(l+r)/2;
if (check(mid)) r=mid//这里就是check代表这个答案可以,但是我还想找更小的,先记录这个答案
else l=mid+1;//代表这个答案不行,太小了,那就跳过这个答案
}
printf("%d",l); //r也可以

NO.2关于一个小问题的总结----mid=(l+r+1)/2 or mid=(l+r)/2,(这个1加还是不加嘞(手动狗头)

直接记模板,如果是l=mid,那必须+1,如果是r=mid,那就不加一。(当l=mid并且l=r-1时会发生死循环,大家可以带入试试)。

模板如下

ll l=0,r=2e9;
while(l<r) {
ll mid=l+(r-l+1)/2;
//if(check(mid))l=mid;
if(a[mid]<=x)l=mid;
else r=mid-1;
}

 

while (l<r)
{
int mid=(l+r)/2;
//if (check(mid)) r=mid//这里就是check代表这个答案可以,但是我还想找更小的,先记录这个答案
if(a[mid]>=x)r=mid;
else l=mid+1;//代表这个答案不行,太小了,那就跳过这个答案
}