我有以下问题要解决:
给定N个整数形成集合S和另一个整数A(与给定的N个整数中的任何一个不完全相同),找到集合S中最接近整数A的整数。
我首先认为这是一个NNS(最近邻搜索)问题,但在NNS中,整数A也必须来自集合S,在我的情况下它不一定是。
然后我考虑将S中的每个整数放入二叉搜索树并搜索第一次出现,其中一个子项小于查询,父项比查询大,但我不知道这是否有效。
我应该使用哪种数据结构?谢谢。
编辑:忘了提到我需要这个比O(n)好,O(logn)足够好。因此我不能使用线性搜索。答案 0 :(得分:2)
您的问题是排序数组/列表中二进制搜索的典型输入。唯一的困难是要注意四个案例(请参阅我们的C#实现)。在C#case
中,二进制搜索通常可以作为标准库的一部分找到https://msdn.microsoft.com/en-us/library/y15ef976(v=vs.110).aspx
private static int Closest(int[] S, int A) {
int index = Array.BinarySearch(S, A);
if (index >= 0)
return S[index]; // exact match, A in S
else if (index == -1)
return S[0]; // A is less than any item in S
else if (index < -S.Length)
return S[S.Length - 1]; // A is greater than any item in S
else { // A is in [left..right] range
// C# specific range encoding; consult your languages/library manual
int left = ~index - 1;
int right = ~index;
if (Math.Abs(S[left] - A) < Math.Abs(S[right] - A))
return S[left];
else
return S[right];
}
测试:
int[] array = new[] { 10, 20, 30, 40, 50 };
// 10
Console.Write(Closest(array, 11));
// 20
Console.Write(Closest(array, 19));
// 10
Console.Write(Closest(array, 4));
// 50
Console.Write(Closest(array, 400));
// 30
Console.Write(Closest(array, 30));
答案 1 :(得分:0)
如果对该集进行排序,您可以轻松修改二进制搜索,以在O(log n)
中找到最接近的整数。你可以想象,你正在寻找一个放置数字位置的地方,所以它仍然是有序的。一旦你通过二进制搜索找到它(在C ++中你可以使用lower_bound
),你只需要检查哪个数字更接近 - 前一个或后一个。
答案 2 :(得分:0)
由于列表已经排序,因此处理是在列表中放置新元素以维护排序顺序的问题。一旦完成位置(比如第i个位置),就从S [i-1]和S [i + 1]计算增量,得到最接近A的整数。