1240:查找最接近的元素
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 11822 通过数: 3950
【题目描述】
在一个非降序列中,查找与给定值最接近的元素。
【输入】
第一行包含一个整数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
【分析】
该题的数据范围很大,如果用线性查找(枚举),m*n=100000*10000=10^9,铁定超时。不过后台数据似乎和给定的数据范围不一致。
【参考代码1】
#include <stdio.h>
#define N 100010
int a[N];
int n;
int search(int x) //线性查找
{
int i,j,res=-1;
if(a[0]>=x)
return 0;
for(i=0;i<n;i++)
{
if(a[i]>=x)
{
if(a[i]==x)
return i;
else
return a[i]-x < x-a[i-1] ? i : i-1;
}
}
return n-1;
}
int main()
{
int i,m,t,res;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
while(m--)
{
res=-1;
scanf("%d",&t);
res=search(t); //返回大于等于t的坐标
if(res==-1)
printf("%d\n",a[n-1]);
else if(res==0)
printf("%d\n",a[0]);
else
{
if(t-a[res-1] <= a[res]-t)
printf("%d\n",a[res-1]);
else
printf("%d\n",a[res]);
}
}
return 0;
}
上述代码直接AC,并未超时,事实上,本题考查的二分查找。
【参考代码2】
#include <stdio.h>
#define N 100010
int a[N];
int n;
int bi_search(int x) //折半查找
{
int left=0,right=n-1,mid;
int res=-1;
while(left<=right)
{
mid=(left+right)/2;
if(a[mid]>=x)
{
res=mid;
right=mid-1;
}
else
{
left=mid+1;
}
}
return res;
}
int main()
{
int i,m,t,res;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
while(m--)
{
res=-1;
scanf("%d",&t);
res=bi_search(t); //返回大于等于t的坐标
if(res==-1)
printf("%d\n",a[n-1]);
else if(res==0)
printf("%d\n",a[0]);
else
{
if(t-a[res-1] <= a[res]-t)
printf("%d\n",a[res-1]);
else
printf("%d\n",a[res]);
}
}
return 0;
}