算法笔记——二分查找

二分查找

经典问题:如何在一个严格递增的序列A中找出给定的数x?

最直接的方法就是:线性扫描序列中的所有元素,如果当前元素恰好为x,则表明查找成功,如果扫描完整个序列,也没有找到x,则表明查找失败

这种顺序查找的时间复杂度为O(n),如果查询次数不多,是很好的选择,但如果需要查询的次数很多,这种方法就不太可行了,进行程序设计竞赛时,会出现运行超时。

更好的办法就是使用二分查找二分查找是基于有序序列的查找算法(以下以严格递增序列为例),该算法一开始令[left,right]为整个序列的下标区间,然后每次测试当前[left,right]中间的位置mid=(left+right)/2,判断A[mid]与欲查询的元素x的大小

  1. 如果A[mid]==x,说明查找成功,退出查询
  2. 如果A[mid]>x,说明元素x在mid的左边,因此往左子区间[left,mid-1]继续查找
  3. 如果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;
}

猜你喜欢

转载自blog.csdn.net/pipihan21/article/details/105019771