二分查找C++
前言
在没有学习数据结构与算法前,我们要在一串序列中查找某个数,往往采用的是for(i=0;i<N;i++)的方式,这样的时间复杂度是O(n),在很多的题里面会受到限制,那么有没有一种方式的时间复杂度更低,也能完成一样的目的呢?在这里我们首先选用的是二分查找法
一、二分查找是什么?
二分查找故名思意,是可以在一个数组中查找一个元素n的方式,其本质的思想是分而治之,将一个序列进行有序化,再将其分成begin······mid,mid+1······end两个区域,对比查找n是begin到mid这个区域,还是mid+1到end这个区域,查找到后再在这个区域中进行同样的操作,直至其begin==end时,即找到该元素n的下标,
通过计算我们可以得到这种方式的时间复杂度是O(log n),与O(n)相比在时间上得到了提升
二、使用步骤
手写函数实现模板
代码如下(示例):
int a[N];
int find(int begin,int end,int n){
while(begin<end){
int mid=(begin+end)/2;
if(a[mid+1]<=n) begin=mid+1;
else end=mid;
}
return begin;//此时begin=end,所以返回哪个都一样
}
2.C++中STL的使用方法(模板)
代码如下(示例):
int count1=lower_bound(a.begin(),a.end(),x);//此语句返回的是函数更低的上界
int count2=upper_bound(a.begin(),a,end(),x);//此语句返回的是函数更高的上界
//上面返回的都是下标,如果需要该数则可以a[begin]
//对于上界的更高和更低可以在csdn上搜所查看一下
int count=conut2-count1;//此语句用了更高的上界减去更低的上界,也就是找到了在该序列中这个元素的个数,属于二分查找的基础应用
三.例题讲解
洛谷P1102 A-B数对
思路:
该题目中A-B=C,如果我们进行两个for循环的暴力求解一定可以得到答案,但是时间复杂度O(n2),是不能拿到满分的,所以我们就需要采取其他的办法,这里我们就使用了二分查找法,我们可以只枚举一个A,因为根据题意,C已知,则B可以转化为B=A-C,也就是说我们只需要对其中的A进行枚举,同时找到A[i]-C这个点的lower_bound和upper_bound,用一个累加器ans来累加upper_bound()-lower_bound(),也就是A[i]这个元素的数对对数,最后输出ans即为答案
代码如下
#include<bits/stdc++.h>
using namespace std;
const int n = 2e5 + 10;
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int M, N;
cin >> M >> N;
int a[n];
for (int i = 0; i < M; ++i) cin >> a[i];
sort(a, a + M);
long long ans = 0;
for (int i = 0; i < M; i++) {
auto L = upper_bound(a, a + M, a[i] - N);
auto R = lower_bound(a, a + M, a[i] - N);
ans += L - R;
}
cout << ans << endl;
return 0;
}
总结
本人天津财经大学22届在读本科生,这是我的第一篇博客,最近在学蓝桥杯的内容,也就边学边写了,有觉得睡眠哥(本人自起)写的好的可以动动美丽的小手点个赞哇,每一个赞都会成为睡眠哥坚持下去的动力!!!谢谢大家