相对于普通的顺序查找,二分查找具有极好的效率。
使用条件:要求线性表必须采用 顺序存储结构 ,而且表中元素按关键字 有序排列 。
二分查找的时间复杂度:O(logn)
手写二分查找
#include <bits/stdc++.h>
#define MAXN 1000005
int a[MAXN];
int main()
{
int n,m; std::scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) std::scanf("%d",&a[i]);
for(int i=1;i<=m;++i)
{
int l=1,r=n,x; std::scanf("%d",&x);
//二分部分
while(r>=l)//=
{
int mid=l+r>>1;
if(a[mid]<x)l=mid+1;
//+-对称
else r=mid-1;
}
if(a[l]==x) std::printf("%d ",l);
//l或r都可以
else std::printf("-1 ");
}
return 0;
}
STL lower_bound模板
lower_bound:二分查找,找出第一个大于等于指定数的位置(迭代器)。如果没有找到,返回最后一个数据的后一个位置。
#include <bits/stdc++.h>
#define MAXN 1000005
int a[MAXN];
int main()
{
int n,m; std::scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) std::scanf("%d",&a[i]);
for(int i=1;i<=m;++i)
{
int x; std::scanf("%d",&x);
int j=std::lower_bound(a+1,a+n+1,x)-a;
//指针减,得到下标
if(a[j]!=x) std::printf("-1 ");
else std::printf("%d ",j);
}
return 0;
}
手写二分的测评结果:
lower_bound的测评结果:
对比可以看出,手写二分的时间是略快于lower_bound的。说明lower_bound的时间复杂度常数较大。
但lower_bound的代码相对于手写二分简单。两者各有利弊。
做题感悟:
- 题目中常常出现的是运用二分查找的思想,灵活变通的运用二分,并不是简简单单的查找数值,所以要熟练的掌握手写二分。