在集合

时间:2018-01-24 15:36:15

标签: c# search nearest-neighbor

我有bool[,],并且输入Vector2(x,y),我想找到最近的true的索引。我可以天真地遍历2d数组并检查输入的距离,但这将给我一个O(LxW)的运行时间。我想知道是否有更快的方法找到最接近O(LxW)。我愿意在Hashset<Vector2>或排序的List<Vector2>或任何其他类型的集合中添加所有真实坐标,如果它能更快地查找。

性能比此处的代码可读性更重要。

示例:

T, T, F
T, F, T
T, T, T

GetNearestTrue(new Vector2(2, 3)) // returns (1, 2)
GetNearestTrue(new Vector2(1, 1)) // returns (0, 1) or (1, 0) or (1, 2) or (2, 1), since they're equidistant it doesn't matter

2 个答案:

答案 0 :(得分:2)

如果你有大量的“假”,那么就有更快的方法。您可以从O(L * W)= O(nFalse + nTrue)优化到 O(log nTrue)。

您可以使用multidim-index(四叉树,kd-tree,R-Plus-Tree,PH-Tree)并插入每个&#39; true&#39; at(x,y)带坐标(x,y)的多维度索引中的一个点。 现在,找到最近的&#39; true&#39;对于一个点&#39; p&#39;,你只需在索引中进行最近邻搜索即可获得点数&#39; p&#39;。例如,this表示存在一种算法&#34;它声称保证了O(log n)的复杂性。&#34;

虽然kd-tree可能是最简单的(对于许多索引,请参阅here for Java实现),但PH-Tree可能有意义,因为它可以直接使用整数作为坐标,而不是浮点值。但是,我不知道PH-Tree的C#版本。

答案 1 :(得分:1)

是否有更快的方法找到最接近的O(LxW)?

如果L和W分别是2d阵列的长度和宽度,则答案为否。

简单证据: 想象一下,你必须证明网格中没有最接近的真实。 I.E.网格只包含false。在访问网格的每个单元格之前,你永远不能说没有。这意味着运行时间始终至少为O(LxW)。

为了证明节点(x,y)离(a,b)最近,你必须证明在半径为|Max(x-a, y-b)|的(a,b)周围的圆中只有假而且在最坏的情况下,半径将是Max(L, W),这使得最坏情况下的运行时间为O(LxW)

虽然您可以通过从中心执行BFS来进行一些优化,但这会通过某些因素减少运行时间,但更糟糕的情况保持不变。