原题链接: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;
}