我有一组轴对齐的矩形。当两个矩形重叠(部分或完全)时,它们将合并到它们的公共边界框中。此过程以递归方式工作。
检测所有重叠并使用union-find形成组,您最终合并 将无效,因为两个矩形的合并覆盖了更大的区域并可以创建新的重叠。 (在下图中,合并了两个重叠的矩形后,会出现新的重叠。)
在我的情况下,矩形的数量是中等的(比如N <100),可以使用强力解决方案(尝试所有对,如果发现重叠,则从头开始合并并重新启动)。无论如何,我想降低复杂性,在最坏的情况下可能是O(N³)。
有任何建议如何改善这个?
答案 0 :(得分:1)
我认为R-Tree会在这里完成工作。 R-Tree索引矩形区域,允许您在O(log n)中插入,删除和查询(例如,交叉查询)低维度的“普通”查询。
我们的想法是连续处理您的矩形,对于您执行以下操作的每个矩形:
对当前R-Tree执行交叉查询(空中的 开始)
如果有结果,则从R-Tree中删除结果, 将当前矩形与所有结果矩形合并并插入 新合并的矩形(最后一步跳转到第1步。)。
总共会执行
理论上你应该使用 O(n log n),但是最后的合并步骤(使用大矩形)可能选择性低,需要的时间超过O(log n),但是根据数据分布,这不应该破坏整个运行时间。
答案 1 :(得分:0)
使用平衡的标准化四叉树。
规范化:收集所有x坐标,对它们进行排序,并用排序数组中的索引替换它们。 y坐标也一样。
平衡:构建四叉树时始终在中间坐标处分割。
因此,当你得到一个矩形时,你想要用树的一些id标记树中正确的节点。如果您在下面找到任何其他矩形(这意味着它们将重叠),请将它们聚集在一组中。完成后,如果向量不为空(您找到重叠的矩形),那么我们创建一个新的矩形来表示子矩形的并集。如果计算的矩形大于您刚插入的矩形,则使用新计算的矩形再次应用算法。重复此操作直到它不再生长,然后移动到下一个输入矩形。
对于性能,四叉树中的每个节点都存储与该节点重叠的所有矩形,并将其标记为终端节点。
复杂性:初始标准化为O(NlogN)
。插入和检查重叠将为O(log(N)^2)
。您需要对原始N矩形以及重叠执行此操作。每次找到重叠时,都会消除至少一个原始矩形,这样您最多可以找到(N-1)个重叠。总的来说,你需要2N的操作。总的来说,复杂性将是O(N(log(N)^2))
。
这比其他方法更好,因为您不需要检查任何到任何矩形的重叠。
答案 2 :(得分:0)
这可以使用平面扫描和空间数据结构的组合来解决:我们沿扫描线合并交叉矩形,并将扫描线后面的任何矩形放到空间数据结构中。每当我们得到一个新合并的矩形时,我们会检查与这个新矩形相交的任何矩形的空间数据结构,如果找到则合并它。
如果扫描线后面的任何矩形(R)与扫描线下的某个矩形(S)相交,则最靠近扫描线的R的两个角中的任何一个都在S内。这意味着空间数据结构应存储点(两点)对于每个矩形)并回答有关位于给定矩形内的任何点的查询。实现这种数据结构的一种显而易见的方法是分段树,其中每个叶子包含在相应的y坐标处具有顶侧和底侧的矩形,并且每个其他节点指向包含最右边的矩形的其后代之一(其右侧最接近于扫线)。
要使用这样的分段树,我们应该压缩(标准化)矩形角的y坐标。
最坏情况时间复杂度由段树确定:O(n log n)。空间复杂度为O(n)。