【问题标题】:Finding nearest element in a set of integers在一组整数中找到最近的元素
【发布时间】:2017-01-01 03:12:51
【问题描述】:

我有以下问题需要解决:

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

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

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

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

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

【问题讨论】:

  • 你的集合是否已排序?
  • 如果只有一个A,那么线性搜索有什么问题?
  • @PulkitGoyal 是的,它已排序。顺便说一句,忘了提到我在 O(logn) 中需要这个。现在要编辑我的问题。
  • 只是一个带二分查找的排序数组/列表?
  • 对小于或等于 A 的数字进行二分搜索,只需将其与下一个最接近的数字进行比较即可。也可以处理极端情况。

标签: algorithm data-structures


【解决方案1】:

您的问题是在有序数组/列表中进行二分搜索 的典型输入。唯一的困难是了解 四种 案例(请参阅我的 C# 实现)。二进制搜索通常可以作为标准库的一部分找到,在 C# 案例中

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));

【讨论】:

    【解决方案2】:

    如果集合已排序,您可以轻松修改二进制搜索以在O(log n) 中找到最接近的整数。您可以想象,您正在寻找在集合中放置数字的位置,因此它保持排序状态。一旦通过二分搜索找到它(在 C++ 中,您可以使用 lower_bound),您只需检查哪个数字更接近 - 之前的数字或之后的数字。

    【讨论】:

      【解决方案3】:

      由于列表已经排序,因此将其视为在列表中放置新元素以保持排序顺序的问题。一旦确定了位置(比如第 i 个位置),从 S[i-1] 和 S[i+1] 计算 delta,以获得最接近 A 的整数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-07
        • 2016-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-17
        • 2023-03-20
        • 1970-01-01
        相关资源
        最近更新 更多