题目贴上:
在一个非降序列中,查找与蒜头君的给定值最接近的元素。
输入格式
第一行包含一个整数 n,为非降序列长度。1≤n≤100000。
第二行包含 n 个整数,为非降序列各元素。所有元素的大小均在 0∼1,000,000,000 之间。
第三行包含一个整数 m,为要询问的给定值个数。1≤m≤10000。
接下来 m 行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在 0∼1,000,000,000 之间。
输出格式m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个。
Sample Input
3
2 5 8
2
10
5
Sample Output
8
5
题目思路:
我们可以把问题这样子拆解:题目给定一个目标数,要求在数组里面找一个数使得两者之差绝对值最小且此时在数组里面找到的数尽量小,我们分别找两个数:大于或等于目标数的最小数,小于或等于目标数的最大数。但我们没必要去两次二分,我们直接求最小数,而最大数一定是和最小数相邻的。
但应该考虑一种特殊情况,如果数组里面所有的数都比目标数大的时候,我们应该直接输出数组里面最小的数。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
const int MAX = 1e6 + 10;
const int INF = 0x7fffffff;
typedef long long int ll;
using namespace std;
ll a[MAX];
int n, k, m,score;
ll cnt = 0;
void Sovle()
{
int l = 0, r = n - 1, mid;
while (l < r)
{
mid = l + (r - l) / 2;
if (a[mid] >= score) r = mid; //查找第一个最大的那个数字
else l = mid + 1;
}
//查找最后一个最小的数字
if (score < a[0])
//如果数组里面所有的数都比目标数要大输出数组里面最小的数
{
cout << a[0] << endl;
return;
}
cout << ((abs(a[r - 1] - score) > abs(a[r] - score)) ?
a[r] : a[r - 1] )<< endl;
}
int main(void)
{
cin >> n;
for (int i = 0;i < n;++i)
cin >> a[i];
cin >> m;
while (m--)
{
cin >> score;
Sovle();
}
return 0;
}