01:查找最接近的元素

NOI 1.11.1 查找最接近的元素

题目:查找最接近的元素

描述

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

输入

第一行包含一个整数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

限制条件

总时间限制: 1000ms 内存限制: 65536kB

思路:

在基础二分的思想下,我们很容易想到对数组里的数进行二分查找。

如果要查找的数在数组中存在,那么定义的函数直接返回该值。如果不存在,那么二分查找的左端点和右端点会停留在目标数的左右两端。

此时,只要将左端点和右端点所对应的数组中的值与目标数进行比较,差值小的即最接近目标数。要注意的是:计算差值需要加绝对值

但是只想到这里明显是不够的,此题存在陷阱

因为我们进行二分查找的前提是要对目标数组进行排序,这里我们以升序为例:

​ 如果目标数小于该数组中的最小值那么右端点将会在数组中越界,导致奇奇怪怪的错误。

​ 如果目标数大于该数组中的最小值那么左端点将会在数组中越界,也会导致奇奇怪怪的错误。

因此,我们要进行特判:

​ 如果目标数小于该数组中的最小值,那么最后直接输出数组中最小的数,反之亦然。

题解:
#include<iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define int long long//将long long 变为int此题数据有点大
using namespace std;
int binaryseach(int a[], int size, int p)//函数作用:在长度为size+1(因为我习惯下标从1开始)的a数组里查找最接近p的数
{
    int l = 1, r = size;//设置左右端点
    while (l <= r)//二分模板
    {
        int mid = l + (r - l) / 2;//若用(l+r)/2可能在某些题中会导致数据溢出
        if (p == a[mid])
        	return p;
        else if (p < a[mid])
        	 r = mid-1;
        

        else if (p > a[mid])
        	 l = mid+1;
    }
    if (p < a[1])//特判
        return a[l];
    else if (p > a[size])
        return a[r];
    else//比较最接近p的数
    {
        int x1 = abs(a[l] - p);
        int x2 = abs(a[r] - p);
        if (x1 < x2)
            return a[l];
        else
            return a[r];
    }

}
signed main()//因为上面将long long 变为了 int 而main函数类型不能为 long long ,故改为signed
{
    int n;
    cin >> n;
    int arr[100010];
    for (int i = 1; i <= n; i++)
    {
        cin >> arr[i];
    }
    sort(arr + 1, arr + 1 + n);//排序
    int num;
    cin >> num;
    while (num--)
    {
        int x;
        cin >> x;
        cout << binaryseach(arr, n, x) << endl;
    }
    

    return 0;

}
上一篇:【財務会計】為替予約


下一篇:SSL证书类型价格和购买