我有一个具有非常特定的算法需求的程序。我需要搜索一个数字列表,以找到最符合一对搜索号的列表中的位置。我将“最佳对齐”定义为该对齐时差异的总和。
例如,如果我有以下数字列表:
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 -- -- --
我目前正在使用一种明显的蛮力方法 - 只需找到每个路线的差异并记住最佳路线。但是,这对我的程序来说是一个瓶颈,所以任何改进都会有所帮助。
我提出的唯一优化有点微不足道:如果对齐,则对中第一个数字的差异超过当前最佳总差异,跳到下一个对齐而不必费心检查对中的第二个数字。它有所帮助,但并不多。
如果相关,则会多次搜索列表,因此如果有某种初始排序可以加快未来的搜索速度,我会感兴趣。
我很欣赏任何人的想法,即使它只是指向相关算法的维基百科页面的链接。谢谢!
答案 0 :(得分:2)
您可以将此问题重新设置为2D中的最近邻搜索。取所有数字对,并将它们视为2D平面的点。您的距离函数称为1范数(绝对差值之和)。使用查询对,您正在寻找最近的点。
因此,您正在寻找的是具有1范数距离的2D最近邻搜索的快速解决方案。众所周知,在O(N.Log(N))预处理需要O(N)存储(构建Voronoi图)之后,所有查询都可以在时间O(Log(N))内得到答案。
或者(对于更简单的实现),您可以使用2D树(2D维度中的kD树)。 http://en.wikipedia.org/wiki/Kd-tree
如果您能够负担得起存储空间,也可以使用网格化解决方案:在点上绘制一个方格,并按照每个图块对它们进行分组。对于查询对,请在网格中找到它,然后在同心圆圈中探索此图块"邻近的瓷砖,并与它们包含的点进行详尽的比较。
答案 1 :(得分:1)
正如@Yves_Daoust所说,你可以将列表中的对表示为2D点。 然后,您可以将它们放在四叉树http://en.wikipedia.org/wiki/Quadtree中。搜索最近的任意点在此结构中以O(lg(n))时间执行。
答案 2 :(得分:0)
您可以保留一个辅助数组,用中间点(l, u)
和宽度m
加上列表中的原始索引来描述对w
。对该数组进行排序并使用二进制搜索来查找中心点的最接近匹配。那么你最好的对齐就应该在那场比赛的附近。
您的标准
d = abs(l1 - l2) + abs(u1 - u2)
然后将成为
d = abs(dm - dw/2) + abs(dm + dw/2), dm = m1 - m2, dw = w1 - w2
这就留下了你应该看二进制搜索找到的匹配程度的问题。你可以从那里开始,在列表中向前和向后工作,直到中间点之间的差异大于你的最佳距离。