关于二分算法的一些感悟

108 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

二分概念

先给大家讲个笑话

有一天阿东到图书馆借了 N 本书,出图书馆的时候,警报响了,于是保安把阿东拦下,要检查一下哪本书没有登记阿东准备把每本书在报警器下过一下来找出引发警报的书,但是保安露出不屑的眼神:你连二分查找都不会吗?于是保安把书分成两堆,让第一堆过一下报警器,报警器响;于是再把这堆书分成两堆… 最终,在检测了 log2N 次之后,保安成功找到了那本引起警报的书,露出了得意和嘲讽的笑容。于是阿东背着剩下的书走了。从此,图书馆丢了 N-1 本书

通过上面的问题我们来解决几个问题:

为什么保安要嘲讽阿东呢?

因为阿东使用的查找方法十分低效

为什么说阿东思维不行,“技术”也不行呢

因为阿东除了没有想到高效的查找思想,而且如果一本本的检查可能一本书都“顺”不出去

为什么保安用“二分查找”最多只要找log2N次呢

因为在二分的过程中每次可以排除一半的选项,因此最坏情况下我们也只需要log2N次查找

二分具体应用

要注意二分的适用场景

二分查找并不简单,发明KMP算法的Knuth大佬说过二分查找的特点是:

思路很简单,细节是魔鬼

\

int chazhao(int arr[], int zhi) {
    int r = n, l = 1,ans=0;
    while (l < r) {//查找数组中第一个大于待查值的元素下标
        int mid = l + (r - l) / 2;//防止变量上溢
        if (arr[mid] == zhi) { ans = mid; return ans; }
        else if (arr[mid] < zhi)l = mid + 1;
        else if (arr[mid] > zhi)r = mid;
    }
    return ans;
}

具体代码如下:

int Lower_bound(int arr[], int zhi) {
    int r = n, l = 1;
    while (l < r) {//查找数组中第一个大于等于待查值的元素下标
        int mid = l+(r-l)/ 2;
        if (arr[mid] >= zhi)r = mid;
        else l = mid + 1;
    }
    if (arr[l] == zhi)return l;
    else return -1;
}

越界情况分析

本次文章是由本人之前讲课的ppt转化过来的,可能观感不是很好,有空会调整一下排版的。