CCF NOI1044. 最近元素【二分查找】

原题链接:1044. 最近元素

时间限制: 1000 ms  空间限制: 262144 KB  具体限制  

题目描述

在一个非降序列中,查找与给定值最接近的元素。

输入

第一行包含一个整数n,为非降序列长度。1 <= n <= 100000。
第二行包含n个整数,为非降序列各元素。所有元素的大小均在0-1,000,000,000之间。
第三行包含一个整数m,为要询问的给定值个数。1 <= m <= 10000。
接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1,000,000,000之间。

输出

m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个。

样例输入

3
2 5 8
2
10
5

样例输出

8
5

数据范围限制

1 <= n <= 100000。

题记:

这道题算是一道二分查找裸题,接下来简单介绍下二分查找,不需要看的跳过直接看代码就好。

二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好,占用系统内存较少;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表

实现步骤:首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

说起来抽象,看代码你就懂了。

ps:二分查找部分的代码可以拷贝下来,再遇到需要使用的题直接粘贴~

C++程序如下:

//NOI1044.最近元素 
#include <iostream>
#include <stdlib.h>
 
using namespace std;
const int  N = 100000;
int a[N];

//二分查找 
int find(int start, int end, int x)
{
    int mid;
 
    while(start < end) {
        mid = (start + end) / 2;
 
        if(a[mid] > x)
            end = mid;
        else
            start = mid;
 
        if(start + 1 == end) {
            if(abs(x - a[start]) > abs(x - a[end]))
                start = end;
            else
                end = start;
        }
    }
 
    return start;
}
 
int main(void)
{
    int n, m, x, i;
 
    cin >> n;
    for(i=0; i<n; i++)
        cin >> a[i];
 
    cin >> m;
    for(i=1; i<=m; i++) {
        cin >> x;
 
        // 二分查找
        int anspos = find(0, n - 1, x);
 
        cout << a[anspos] << endl;;
    }
 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fyy_lufan/article/details/82533708