在一组整数中查找最近的元素

时间:2016-12-31 13:33:57

标签: algorithm data-structures

我有以下问题要解决:

给定N个整数形成集合S和另一个整数A(与给定的N个整数中的任何一个不完全相同),找到集合S中最接近整数A的整数。

我首先认为这是一个NNS(最近邻搜索)问题,但在NNS中,整数A也必须来自集合S,在我的情况下它不一定是。

然后我考虑将S中的每个整数放入二叉搜索树并搜索第一次出现,其中一个子项小于查询,父项比查询大,但我不知道这是否有效。

我应该使用哪种数据结构?谢谢。

编辑:忘了提到我需要这个比O(n)好,O(logn)足够好。因此我不能使用线性搜索。

3 个答案:

答案 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的整数。