第十九章:二分查找和二分答案

二分查找

二分的思想在程序设计中有着广泛的应用,例如,排序算法中的快速排序、归并排序,数据结构中的二叉树、堆、线段树等。二分是一种常用且高效的算法,它的基本用途是在单调序列中进行查找和判定操作。

二分查找算法思想

对于n个有序且没有重复的元素(假设为升序),从中查找特定的某个元素x,我们可以将有序序列分成规模大致相等的两部分,然后取中间元素与要查找的元素x进行比较,如果x等于中间元素,则查找成功,算法终止;如果x小于中间元素,则在序列的前半部分继续查找,否则在序列的后半部分继续查找。这样就可以将查找的范围缩小一半,然后在剩余的一半中继续重复上面的方法进行查找。

这种每次都从中间元素开始比较,并且一次比较后就能把查找范围缩小一半的方法,叫作二分查找。二分查找的时间复杂度是 O(logN),是一种效率较高的查找算法。

时间复杂度O(logN)

在常见的时间复杂度中,时间复杂度为O(logN)的算法十分高效,当数据规模增大n信时,耗时增大logN倍(这里的log以2为底)。例如,当数据增大256倍时,耗时增大8倍,因为2的8次方等于256。二分查找算法的时间复杂度为O(logN),每次查找排除掉一半的可能,1024个有序数据中最多查找10次就可以找到目标。

二分查找算法描述

用一维数组a存储有序元素序列,用变量low和high分别表示查找范围中第一个元素和最后一个元素的下标,mid表示查找范围的中间位置对应元素的下标,x为要查找的元素。

(1)变量初始化,令low=1,high=n。low和high分别初始化为有序序列的第一个元素和最后一个元素的下标。

(2)判断查找范围low≤high是否成立,如果成立,执行(3),否则输出"-1"(表示没有找到),结束算法。

(3)取中间元素,令mid=(low+high)/2,a[mid]就是中间元素。

(4)比较a[mid]与x,如果a[mid]等于x,则查找成功,结束算法;如果x

例如,从10个元素13,15,18,22,28,34,56,65,70.80中查找元素22的过程如图111-1所示最坏的情况下 4次可以找到。

特别注意:使用二分查找时,必须保证数据是有序的,若数据是无序的,则需要使用排序算法将数据变得有序。

二分查找算法的框架如下:

int ef(int a[],int n,int x)
{
    int low=1,high=n,mid;
    while(low<=high)   //判断查找范围low<=high是否成立 
    {
        mid=(low+high)/2;   //取中间元素的位置 
        if(x==a[mid])    //x已经找到 
        {
            return mid;    //返回x对应的下标 
        }
        else if(x

Copy

思考:为什么while循环的条件中是“<=”,而不是“<”?

例题1:查找m个数(主题库2646)

请你输入一个含 nn 个数字的不重复数列,请你高速的在这个数列中寻找 mm 个数字 x_1,x_2,...,x_mx1​,x2​,...,xm​ ,如果能找到直接输出,如果不存在输出 -1−1 ,用换行隔开(0

输入格式:

输入共 4 行,第一行,为一个数字 nn 。第二行为 nn 个数字。第三行为一个数字 mm 。第四行为 mm 个要寻找的数字。

输出格式:

输出共 mm 行,每行一个数字,如果能找到直接输出原数字,如果找不到,输出 -1−1 。

样例输入

5
1 2 3 4 5 
3
2 1 3

Copy

样例输出

2
1
3

Copy

问题分析

解法一:暴力,样例没问题,提交0分。

#include 
using namespace std;
int a[1000001];
int main()
{ 
    int n,m,i,j,t;
    cin>>n; 
    for(i=1;i<=n;i++)
    { 
        cin>>a[i]; 
    }
    cin>>m;
    for(i=1;i<=m;i++)
    { 
        cin>>t;
        for(j=1;j<=n;j++)
        { 
            if(a[j]==t)
            { 
                cout<

Copy

解法2:二分查找+递归

#include 
using namespace std;
int a[1000001];
int lower_bound(int x,int y,int t)
{ 
    if(x>y){ return -1; }
    int h=(x+y)/2;
    if(a[h]==t) { return a[h]; }
    if(a[h]>t)  { y=h-1; return lower_bound(x,y,t); }
    else { x=h+1; return lower_bound(x,y,t); }
}
int main()
{ 
    int n,m,i,j,t;
    cin>>n; 
    for(i=1;i<=n;i++) //一百万次
    { cin>>a[i]; }
    sort(a+1,a+1+n); //n*log(n)2千万次
    cin>>m;
    for(i=1;i<=m;i++)
    { 
        cin>>t; 
   

你可能感兴趣的:(c++,c++)