从给定的事实中有效地获得图表

时间:2016-12-15 18:43:43

标签: algorithm math undirected-graph

我在二维平面上有一组点(xy)说n点。

(x1, y1), (x2, y2), (x3, y3), ......................., (xn, yn)

我的目标是绘制图表。 iff中将连接图中的两个节点(点) abs(difference in x coordinate) + abs(difference in y coordinate) = L(given)

可以O(n*n)完成。是否有可能有效地做到这一点。

BTW我正在尝试解决this问题

5 个答案:

答案 0 :(得分:2)

您可以在O( n log n + E )时间内执行此操作,其中 E 是你最终得到的实际边数(即邻居对的数量)。

对于任何给定点,其允许的邻居位置形成菱形,边长 L √2:

        *
      *   *
    *       *
  *           *
*       o       *
  *           *
    *       *
      *   *
        *

如果按 x + y 对点进行排序,并回退到 x - y ,那么单个O( n + E )通过排序点将允许您找到此类型的所有邻居:

        *
          *
            *
              *
        o       *

每个点。 (为此,您使用索引i来跟踪您正在寻找邻居的当前点,并使用单独的索引j来跟踪允许的邻居行,以便 X <子>Ĵ - ý <子>Ĵ = X <子> I - < em> y i + L 。这听起来像是O( n 2 ),因为你有两个索引进入数组;但诀窍是j随着i单调递增,所以ij中的每一个只生成一个单< / em>传递数组。这甚至可以是O( n )传递,除非你找到( x i sub>, y i ),那么你需要将它们重新视为( x i + 1}的潜在邻居 y i + 1 ),所以你不能增加j。所以它出现在O( n < / em> + E )传递。)

然后您可以通过 y - x 重新排序它们,并回退到 x + y ,并且重复这个过程找到这些邻居:

        *
      *
    *
  *
*       o

由于邻居是一种对称关系,你实际上并不需要担心剩下的邻居:

        o
  *           *
    *       *
      *   *
        *

(整体O( n 日志 n + E )时间包括O( n log n )对点进行排序的时间加上两个O( n + E )传递的时间。)

答案 1 :(得分:1)

鉴于对数据的某些假设,当然可以有效地做到这一点。我会考虑更一般的情况。例如,如果点均匀分布且相互作用距离L(given)相对于数据的扩展较小,则可以通过对粒子进行分级将问题转换为O(n)

这会将你从左边的情况带到右边的情况:

Binning particles on a plane

bin的大小为>=L(given),对于任何粒子,都会搜索粒子的bin和8个相邻的bin。如果bin中的粒子数平均为d,则问题可在O(9dn)=O(n)时间内解决。

答案 2 :(得分:0)

与上述相关的另一种可能性是使用稀疏矩阵结构将1值存储在所有点的位置,并在其他地方存储0值。

虽然存在很好的库,但你可以通过提出一个结合了xy坐标的哈希来伪造它。在C ++中看起来像:

std::unordered_set< std::pair<int,int> > hashset;

预先设定散列表,这样可能比避免昂贵的重新散列所需的量大30-50%。

将所有点添加到hashset;这需要O(n)时间。

现在,交互距离L(given)定义了一个围绕中心点的菱形。您可以预生成此钻石的偏移列表。例如,如果L=2,则偏移量为:

int dx[]={0,-2,-1,0,1,2, 1,0,-1};
int dy[]={0, 0, 1,2,1,0,-1,2,-1};

现在,对于每个点,循环偏移列表并将它们添加到该点的坐标。这会生成一个隐含的邻居可能位置列表。使用hashset检查该邻居是否存在。这需要O(n)时间,并且如果8L << N(有一些关于可从第一个节点到达的邻居数量的资格),则效率很高。

答案 3 :(得分:0)

我非常喜欢ruakh @的解决方案。另一种方法是允许逐渐增加点集而不损失效率。

要添加每个点P,您需要在树中搜索符合条件的点Q,并在找到任何点时添加边。

在任何k-d树搜索的每个级别,都有可用的每个孩子代表的矩形范围。在这种情况下,只有当它的范围可能包含匹配PIe的点时,您才会继续搜索“向下”进入子节点,该矩形必须包含ruakh @描述的钻石的某些部分。

分析k-d树搜索通常很棘手。我很确定这个算法在一个随机点集的预期O(| E | log n)时间内运行,但是很容易想象性能更好的点集和其他更差的点集。

答案 4 :(得分:-1)

考虑行y = xy = -x 考虑每个点与这些线的距离。 只有当它们与这两条线的距离正确时才连接两个点。 因此,您可以按距离将所有点存储到这些线上。然后在每个桶中,有一个有序的点映射(按它们沿着它们的距离排序)。此有序地图中正确距离内的任何点都应在图表中连接。 应该是N * Log(N)更糟的情况,即使所有的点都在彼此的顶部。