【问题标题】:Algorithm to find a number pair's closest match in a list of numbers在数字列表中查找数字对最接近匹配的算法
【发布时间】:2014-02-28 10:24:27
【问题描述】:

我有一个具有非常特殊算法需求的程序。我需要搜索一个数字列表,以找到列表中与一对搜索数字最匹配的位置。我将“最佳对齐”定义为该对齐处差异的总和。

例如,如果我有以下数字列表:

12  18 -20  45  11  34   6  -8

...我正在搜索 44 13 对,那么算法应该返回 3,因为这种对齐方式是最好的(总差只有 5),而 3 是对齐开始的索引

index:             0   1   2   3   4   5   6   7
list:             12  18 -20  45  11  34   6  -8
search alignment: --  --  --  43  14  --  --  -- 
difference:       --  --  --   2   3  --  --  -- 

我目前正在使用一种明显的蛮力方法 - 只需找到每个对齐的差异并记住最好的。但是,这对我的程序来说是一个瓶颈,所以任何改进都会有所帮助。

我提出的唯一优化有点微不足道:如果对于对齐方式,配对中第一个数字的差值超过当前最佳总差值,则跳到下一个对齐方式,而无需检查配对中的第二个数字.有帮助,但作用不大。

如果相关,列表会被搜索多次,所以如果有某种初始排序可以加快未来的搜索速度,我会很感兴趣。

我会很感激任何人的任何想法,即使它只是指向相关算法的维基百科页面的链接。谢谢!

【问题讨论】:

    标签: algorithm search


    【解决方案1】:

    您可以将此问题重新定义为二维中的最近邻搜索。取所有成对的数字,并将它们视为 2D 平面的点。您的距离函数称为 1-范数(绝对差之和)。使用您的查询对,您正在寻找最近的点。

    因此,您正在寻找的是 2D 中最近邻搜索的快速解决方案,距离为 1 范数。众所周知,经过O(N.Log(N))的预处理需要O(N)的存储(Voronoi图的构建),所有查询都可以在O(Log(N))时间内得到答复。

    或者(对于更简单的实现),您可以使用 2D-tree(2D 维度中的 kD-tree)。 http://en.wikipedia.org/wiki/Kd-tree

    如果您负担得起存储费用,也可以使用网格解决方案:在您的点上绘制一个方形网格,并将它们按图块分组。对于查询对,将其定位在网格中,并从该图块中以相邻图块的同心“圆圈”进行探索,并与它们包含的点进行详尽的比较。

    【讨论】:

    • 同心“圆”是危险的。点 (6, 6) 比点 (10, 1) 更接近 (0, 0)。但就我们的任务而言,后者比前者更好。
    • 对于 1 范数距离,圆圈是菱形。
    【解决方案2】:

    正如@Yves_Daoust 所说,您可以将列表中的对表示为二维点。 然后,您可以将它们放在四叉树http://en.wikipedia.org/wiki/Quadtree 中。在此结构中搜索最接近任意点的时间为 O(lg(n))。

    【讨论】:

      【解决方案3】:

      您可以保留一个辅助数组,用中点 m 和宽度 w 加上列表中的原始索引来描述您的配对 (l, u)。对该数组进行排序并使用二进制搜索来找到中心点的最接近匹配。您的最佳对齐应该在该匹配附近。

      你的标准

      d = abs(l1 - l2) + abs(u1 - u2)
      

      会变成

      d = abs(dm - dw/2) + abs(dm + dw/2), dm = m1 - m2, dw = w1 - w2
      

      这就留下了一个问题,即您应该查看与二进制搜索找到的匹配多近的问题。您可以从那里开始,在列表中向前和向后工作,直到中点之间的差异大于您的最佳距离。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-23
        • 2019-11-02
        • 1970-01-01
        • 2018-01-02
        • 1970-01-01
        相关资源
        最近更新 更多