二分查找
经典问题:如何在一个严格递增的序列A中找出给定的数x?
最直接的方法就是:线性扫描序列中的所有元素,如果当前元素恰好为x,则表明查找成功,如果扫描完整个序列,也没有找到x,则表明查找失败
这种顺序查找的时间复杂度为O(n),如果查询次数不多,是很好的选择,但如果需要查询的次数很多,这种方法就不太可行了,进行程序设计竞赛时,会出现运行超时。
更好的办法就是使用二分查找二分查找是基于有序序列的查找算法(以下以严格递增序列为例),该算法一开始令[left,right]为整个序列的下标区间,然后每次测试当前[left,right]中间的位置mid=(left+right)/2,判断A[mid]与欲查询的元素x的大小
- 如果A[mid]==x,说明查找成功,退出查询
- 如果A[mid]>x,说明元素x在mid的左边,因此往左子区间[left,mid-1]继续查找
- 如果A[mid]<x,说明元素x在mid位置的左边,因此往右子区间[mid+1,right]继续查找
二分查找的高效之处在于。每一步可以去除当前区间中的一半元素,因此其时间复杂度为O(logn),这是十分优秀的
二分查找
#include<bits/stdc++.h>
using namespace std;
int BannarySearch(int a[],int left,int right,int x) {//数组,二分下边界,二分上边界,查找数字,
//传初值为[0,n-1]
int mid;
while(left<=right) {
mid=(left+right)/2;
if(a[mid]==x)
return mid;
else if(a[mid]>x)//当为递减序列时,改为a[mid]<x
right=mid-1;
else
left=mid+1;
}
return -1;//查找失败
}
void Arrange(int a[],int n) {//按递增排序
for(int i=0;i<n-1;i++)
for(int j=i+1;j<n;j++)
if(a[i]>a[j]) {
int t;
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
int main()
{
int n,x;
cin>>n>>x;
int a[n]={0};
for(int i=0;i<n;i++)
cin>>a[i];
Arrange(a,n);
cout<<BannarySearch(a,0,n-1,x)<<endl;
return 0;
}
查找第一个大于或等于元素x的元素的下标
#include<bits/stdc++.h>
using namespace std;
int Lower_bound(int a[],int left,int right,int x) {
int mid;
while(left<right) {
mid=(left+right)/2;
if(a[mid]>=x)
right=mid;
else
left=mid+1;
}
return left;
}
void Arrange(int a[],int n) {
for(int i=0;i<n-1;i++)
for(int j=i+1;j<n;j++)
if(a[i]>a[j]) {
int t;
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
int main()
{
int n,x;
cin>>n>>x;
int a[n];
for(int i=0;i<n;i++)
cin>>a[i];
Arrange(a,n);
cout<<Lower_bound(a,0,n,x)<<endl;
return 0;
}
查找第一个大于元素x的元素的下标
#include<bits/stdc++.h>
using namespace std;
int Lower_bound(int a[],int left,int right,int x) {
int mid;
while(left<right) {
mid=(left+right)/2;
if(a[mid]>=x)
right=mid;
else
left=mid+1;
}
return left;
}
void Arrange(int a[],int n) {
for(int i=0;i<n-1;i++)
for(int j=i+1;j<n;j++)
if(a[i]>a[j]) {
int t;
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
int main()
{
int n,x;
cin>>n>>x;
int a[n];
for(int i=0;i<n;i++)
cin>>a[i];
Arrange(a,n);
cout<<Lower_bound(a,0,n,x)<<endl;
return 0;
}