这位大佬让我看对二分有了更深入的理解。对于二分我的疑惑点在于
while(l<=r)这里,而今看了大佬代码让我解开了疑惑;
假如给出0 2 4 6 8 10 12......200,然后给出一个数比如40,然后你需要在数组中找出一个数存不存在。比如150,枚举在于较多数据的时候太费时间,需要用到二分,先排好序,然后找中间的数.这里是100,150比100大,说明我们只需要102到200,如此分下去就是
O(log2n)的复杂度。
#include<stdio.h>
int main()
{
int a[105];
for(int i=0;i<=100;i++)
{
a[i]=i*2;
}
int n;
while(~scanf("%d",&n))
{
int l=0,r=100,pan,flag=0;
while(l<=r)//不理解这里先后看,不用管,一开始我也不是很懂。
{
pan=(l+r)/2;
if(a[pan]==n)
{
flag=1;//标记存在
break;
}
if(a[pan]<=n)
{
l=pan+1;
}
else
{
r=pan-1;
}
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
}
r为什么会是pan-1而不是pan,l为何不是pan+1不是pan.这里给举个简单的例子,如果输入5,而a[2]存的是4,a[3]存的是6。这时候r会卡在2 和3,无限循环,如下图。


现在加深一下要求,依然
0 2 4 6 8 10 12......200。给出一个数n,如果这个数存在就输出n,不存在输出离他靠右(大于他)的第一个数,例如 :输入12 输出12,输入3输出4 ;
#include<stdio.h>
int main()
{
int a[105];
for(int i=0;i<=100;i++)
{
a[i]=i*2;
}
int n;
while(~scanf("%d",&n))
{
int l=0,r=100,pan;
while(l<=r)
{
pan=(l+r)/2;
if(a[pan]<n)
{
l=pan+1;
}
else
{
r=pan-1;
}
}
printf("ans=%d\n",a[l]);
}
}
现在讲解一下while(l<=r)吧!分两种情况:
第一种:输入99,你会发现a[pan]=100,pan=50,也就是说r跳到了pan-1=49,这时候你会发现L到r的查找范围变成了0 2 4 6 8 10 .......98.这时候因为范围的数都比99小,所以L会一直向右跳,一直到和r一样等于49,这时候因为while(l<=r)L会往右跳一位,也就是50。L就是答案。
第二种:输入101,同上,L变成了51,范围变成了102 104 106 108......200.r会一直左跳一直到52,这时pan=51,所以r=pan-1=50,跳出循环。L就是答案;
如下图:


第三题,0 2 4 6 8....200.,给n,有n输出n,没n输出靠n左边的一位。例如:输入12 输出12。输入3,输出2.
如果上面理解,可以自己打出这个。(都差不多的)
代码如下:
#include<stdio.h>
int main()
{
int a[105];
for(int i=0;i<=100;i++)
{
a[i]=i*2;
}
int n;
while(~scanf("%d",&n))
{
int l=0,r=100,pan;
while(l<=r)
{
pan=(l+r)/2;
if(a[pan]<=n)
{
l=pan+1;
}
else
{
r=pan-1;
}
}
printf("ans=%d\n",a[r]);
}
}
如有错误,或者不足,欢迎大佬指出,共同进步。