二分查找方法

总结

二分查找可能会遇到哪些边界情况?为什么示例代码能完美的解决这些边界情况?

答:总是可以通过问题转换写出满足L < R的优美代码。

  • 二分查找伪代码
while( L < R ) {
    int M = L + (R - L)/2;
    if( 答案在[M + 1,R]中 ) { // 思考一下,什么情况下能够说明“答案在[M+1,R]中”
        L = M + 1;
    } else { // 答案在[L,M]中
        R = M;
    }
}
  • 写二分查找遇到了死循环,考虑是不是遇到了“差一点”问题。

    • 如果代码中是用的L = M,把L不断往右push,那么M向上取整(M = L + (R - L + 1)/2);

    • 如果代码中是用的R = M,把R不断往左push,那么M向下取整(M = L + (R - L)/2)。

  • 代码示例:

    • 有一个从小到大排好序的数组,你要找到第一个大于等于x的数字,应该怎么做?

    输入n,x,以及一个长度为n的数组a(已经从小到大排好序了)

    输入样例:

    9 4

    2 3 3 3 3 4 4 4 4

    • 代码样例:
  • #include <iostream>
    using namespace std;
    
    int n, x, a[100000];
    
    int main() {
        cin >> n >> x; // n为数组元素个数,x为
        // 输入数组
        for( int i = 0; i < n; ++i ) 
            cin >> a[i];
        // 考虑数组中不存在大于等于x的数字的情况
        if( x > a[n-1] ) {           
            cout << -1 << endl;
            return 0;
        }
        
        // 二分查找
        int L = 0, R = n-1;          // 数组下标从0到n-1,闭区间
        while( L < R ) {             // 当区间中至少有两个数字的时候,需要继续二分
            int M = L + (R - L) / 2; // 求出区间中点
            if( a[M] < x ) {         // 答案一定出现在[M+1,R]中
                L = M + 1;
            } else {                 // a[M] >= x,答案一定出现在[L,M]中
                R = M;
            }
        }
        // 此时L == R,a[L]就是第一个大于等于x的数字
        if ( a[L] == x) {
            cout << L << endl;  // 如果答案存在,则输出答案
        } else {
            cout << -1 << endl; // 如果答案不存在,则输出-1
        }
        return 0;

    最后,再回顾一下在上一知识点中,我们推导了二分查找的时间复杂度。只有当我们询问区间中点的时候,我们才能让可行区间的长度以最快的速度变短——每次大约变为原来长度的一半,所以二分查找的时间复杂度是log_2(n)log2​(n)。

    二分查找时间复杂度的计算方法:

    比如,在猜数字的游戏中,假设我们一开始有n个数字。每次把剩余数字的区间分成两半,直到xx次后只剩下最后一个数字,就是我们想要的答案啦。 计算公式如下:

    n * 1/(2^x) = 1n∗1/(2x)=1

    xx次后只剩下最后一个数字

    x = log_2(n)x=log2​(n)

    那么,xx的值就是log_2(n)log2​(n)咯

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值