【算法】二分查找

路人甲:你说,@戚洪昊是不是不玩了?

路人乙:那哪能啊!

路人甲:那他咋不发博客啦?

路人乙:你看,他现在不就发了么...

路人甲:阿巴阿巴……


好吧,我承认上边的东西纯属凑字数

但是我雀食好久没有发博客了

今天给大家带来二分查找的故事~


大家好,我叫二分查找。

听说我干事的效率很快,所以被作者揪出来了。

这么说吧,我可能不算太简单

但是肯定不能把你难倒


先来简要介绍一下我的工作原理吧

使用我这种算法

首先需要定义两个变量——

左边(l)和右边(r)!

自然,还少不了一个变量m(中间)

m的算法为:(l+r)/2

很好的一个公式

看不懂?我来解释一下

现在,有一个数组a[5](排过序的)

1 3 4 6 7

现在要在a数组中找到3 并且输出下标

这里有两种办法:

方法1:朴素枚举(时间复杂度:O(n))

for(int i=0;i<n;i++)
    if(a[i]==key) cout<<i;

方法2:二分查找(时间复杂度:O(log2N))

int binarySearch(int a[], int N, int aa) {
    bool found=false;
    int l=0,r=N,m=0;
    while(l<r) {
        m=(l+r)/2;
        if(a[m] == aa) {
            found=true;
            break;
        }
        if(a[m] > aa) {
            r=m;
        } else if(a[m] < aa) {
            l=m+1;
        }
    }
    if(found)
        return (m+1);
    else
        return -1;
}

由于枚举递增的特性

导致暴力枚举的时间复杂度一定是O(n)

但是我们可以想办法优化

还记得小时候玩的猜数字游戏吗?


甲:我想一个数,你来猜大小

乙:好啊好啊!

甲:我想好了,你猜吧

乙:50?

甲:大了!

乙:25?

甲:小了!

乙:37?

甲:小了!

乙:43?

甲:大了!

乙:40?

甲:小了!

乙:41?

甲:对了!

乙:哈哈哈!


上面就是一个猜数字游戏的标准玩法

可以看到乙猜数字都是对半ka的

这样可以使猜数字的次数最少

二分就运用了这个原理

想到这儿

你是不是顿悟了?

二分的基本原理就是——

大了ka一半,小了ka一半


首先,咱们先来写一个框架:

int l=0,r=N,m=0;
while(l<r){
    ...
}

现在,咱们来给这个只有躯壳的while循环添加灵魂

(阿巴阿巴阿巴[添加灵魂的声音])

好了,现在咱们再来看这个二分循环:

int l=0,r=N,m=0;
    while(l<r) {
        m=(l+r)/2;
        if(a[m] == aa) {
            found=true;
            break;
        }
        if(a[m] > aa) {
            r=m;
        } else if(a[m] < aa) {
            l=m+1;
        }
    }

在这个循环内,首先Middle(m)为l+r的一半 就是(l+r)/2

这就是我们刚刚说的ka~

当然,如果ka完以后Middle下标对应的数就是原数的话就直接打破循环

如果不是的话,你就可以问问数组:

大了还是小了?

如果数组告诉你 大了

那么left(l)就是m+1了

这样,这个数组的大小就变成了从m+1到r

那么数组小了的话

数组的右边界(r)就变成了m

然后就再次循环~

再算一个m

再进行判断~

于是,我们就可以得到他的在函数中的完整代码:

int binarySearch(int a[], int N, int aa) {
    bool found=false;
    int l=0,r=N,m=0;
    while(l<r) {
        m=(l+r)/2;
        if(a[m] == aa) {
            found=true;
            break;
        }
        if(a[m] > aa) {
            r=m;
        } else if(a[m] < aa) {
            l=m+1;
        }
    }
    if(found)
        return (m+1);
    else
        return -1;
}

在这个函数中 a代表传入的数组 N表示数组的大小 aa(随便取得)表示要查找的值

于是,我们就得到了这个算法的概念!

二分查找,顾名思义,就是100分的测试点只能得2分的查找

好吧,其实是

二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好,占用系统内存较少;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。                                                                                         ——360百科

那我们来试几道题练练手吧

 

 

好啦,二分查找就讲到这,大家后会有期~

(有没有期还真不知道) 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值