二分查找个人领悟

本文通过具体实例详细解析了二分查找算法的工作原理及其在不同情况下的应用方式,帮助读者掌握二分查找的基本思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


这位大佬让我看对二分有了更深入的理解。对于二分我的疑惑点在于 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]);
    }
}

如有错误,或者不足,欢迎大佬指出,共同进步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值