二分查找以及序列的二段性

本文详细介绍了二分查找的基本原理和不同变体,包括寻找序列中第一个大于、大于等于、小于、小于等于特定值的元素的下标。通过实例展示了如何避免二分查找的常见错误,并给出了cpp标准库中lower_bound和upper_bound函数的使用方法。同时,文章探讨了二分查找在不同区间上的应用,以及如何处理可能导致死循环的情况,帮助读者深入理解并正确实现二分查找算法。

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

二分查找模板


  以下程序,需给定一个单调不下降整形数组A,整形变量lrv,程序保证返回值i落于闭区间 [l , , ,r] 中。

  假定 [l , , ,r] 中一定存在一个 i

  i满足A[i]<vi最小 (即序列A的左端点):return l;

  i满足A[i]<vi最大 (即vA中的前驱):

while (l < r) {
   
    int mid = l + r + 1 >> 1;
    if (A[mid] < v) l = mid; else r = mid - 1;
}
return l;

  i满足A[i]≤vi最小 (即序列A的左端点):return l;

  i满足A[i]≤vi最大 (即vv的前驱):

while (l < r) {
   
    int mid = l + r + 1 >> 1;
    if (A[mid] <= v) l = mid; else r = mid - 1;
}
return l;

  i满足A[i]>vi最小 (即vA中的后继):

while (l < r) {
   
    int mid = l + r >> 1;
    if (A[mid] > v) r = mid; else l = mid + 1;
}
return l;

  i满足A[i]>vi最大 (即序列A的右端点):return r;

  i满足A[i]≥vi最小 (即vv的后继):

while (l < r) {
   
    int mid = l + r >> 1;
    if (A[mid] >= v) r = mid; else l = mid + 1;
}
return l;

  i满足A[i]≥vi最大 (即序列A的右端点):return r;


可能的实现


#include <algorithm>

template<class itr, class T>
itr lower_bound(itr first, itr last, const T &value){
   
    while (std::distance(first, last)) {
   
        itr mid = first;
        std::advance(mid, std::distance(first, last) / 2);
        if (*mid < value)
            first = ++mid;
        else last = mid;
    }
    return first;
}
#include <algorithm>

template<class itr, class T>
itr upper_bound(itr first, itr last, const T &value){
   
    while (std::distance(first, last)) {
   
        itr mid = first;
        std::advance(mid, std::distance(first, last) / 2);
        if (!(value < *mid))
            first = ++mid;
        else last = mid;
    }
    return first;
}


二分查找

Binary Search


  本文意在一举解决读者可能遇到的:

  1. 写出错误的二分查找
  2. 不知道如何使用二分查找

  等一系列与二分法相关的可能的问题。当然,笔者能力有限,如有不足,望海涵。


问题引入

leading-in


  给定长度为 n n n 的上升序列 A A A,即 A A A 中任意一对元素 a i , a j a_i,a_j ai,aj i < j i < j i<j 都满足 a i < a j a_i < a_j ai<aj,现在有 T T T 个询问,每个询问都会给出一个整数 b b b,你需要回答 b b b A A A 当中的位置,若 b ∉ A b \not\in A bA,则回答 − 1 -1 1


朴素查找


  对于第 t t t 次询问 b t b_t bt,我们可以顺序的取遍 A A A 中的每一个元素,直至第 i i i 个元素 a i = b t a_i = b_t ai=b

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值