【问题标题】:Max number of overlapping rectangles最大重叠矩形数
【发布时间】:2017-10-10 22:49:33
【问题描述】:

我看过这个面试问题,但不知道如何回答: 给定 N 个矩形,找出重叠矩形的最大数量。 例如,对于由左下角和右上角点表示的矩形,[(1, 1), (3, 3)], [(2, 2), (4, 4)], [(1, 3), ( 2, 4)], [(2, 2), (3, 3)],返回 3 因为前两个和最后一个矩形重叠。我可以想到一个时间复杂度为 O(n^2) 的算法,但应该有一个 O(NlogN) 的算法。

【问题讨论】:

  • 先发布解决方案,然后寻求优化帮助。
  • 我想不出一个 O(NlogN) 的解决方案(但无论如何我不是算法专家......)。我可以想到一些替代方法来做到这一点,但不一定比你的 O(n^2) 蛮力解决方案更好。除了你提供的样本数据,我想问面试官输入的数据一般会是什么样子?例如N可以有多大?矩形可以有多大?它们是 [(1, 1), (3, 3)] -ish 大小还是 [(1000, 1000), (30000000, 30000000)] ?
  • 查看 Lucanus Simonson 的 polygon 包算法。他的实现是 C++ BOOST 库的一部分。他开发了一种基于点的多边形演算,将基本的布尔运算(例如交集)减少到线性时间。这应该会有所帮助,尽管我还没有说服自己有一个简单的迭代来利用它来实现所需的解决方案。
  • 你需要使用一些特殊的数据结构比如Fenwick tree或者Segment tree来实现O(n log n)。你知道他们吗?
  • Segment tree 是的,你能简单解释一下这个想法或者给我一些实现O(nlogn)时间复杂度的参考吗?

标签: algorithm


【解决方案1】:

为了找到最大重叠数,我们需要执行以下操作:

  • 将每个矩形分成两段,开端和端,例如对于矩形 [(0,0) (1,1)] -> 我们可以使用两段 [(0,0) (0, 1)] 和 [(1,0), (1,1)] 来表示。

  • 根据 x 坐标对所有这些片段进行排序。

  • 遍历这些段,同时维护一个段树来跟踪矩形:

    • 如果段是打开的并且坐标为 (x,y1) (x,y2) -> 将段树中的段 (y1, y2) 加一。

    • 如果段很接近并且坐标为 (x,y1) (x,y2) -> 将段树中的段 (y1, y2) 减一。

  • 当我们遇到一个开放的段 (x,y1) (x,y2) 时,我们还要检查段树中 (y1,y2) 中存在多少段,这些数字中的最大值是最终结果。

请注意,段树中的每个添加/删除/搜索查询都是 O(log n) -> 我们获得了 O(n log n) 的解决方案。

【讨论】:

  • 谢谢,解释清楚,很有帮助。
  • 如何为这个问题创建分段树? @pham
  • 如何根据上面解释的逻辑创建一个段树?
【解决方案2】:

我的 O(N^2) 算法是这样要求的:

  1. 将所有底部和顶部边缘的 y 轴值与重复项进行排序,在此示例中,我们将得到 (1, 2, 2, 3, 3, 4)。此步骤给出 (NlogN) 时间复杂度。而且对于每个值,我们还需要记录它所属的矩形。

  2. 获取每个矩形左右边缘的所有 x 轴值(每个 2N 个值,在本例中,我们将得到 (1, 2, 3, 4))。对于每个 x 值,我们创建一条穿过 (x, 0) 的垂直线。

  3. 对于每条垂直线,迭代第一步排序的所有值,计算在当前垂直线重叠的矩形的最大数量。我们可以通过扫描线算法在 O(N) 时间内完成(在我们的示例中,在值 1 处,我们有 1 个矩形,然后转到值 2,添加两个矩形,因此 3 个矩形重叠,在值 3 处,添加一个,然后剩下一个,2个矩形重叠)。因此总的来说,它会给出 O(N^2) 的时间复杂度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-02
    • 2023-04-01
    • 2011-01-15
    • 1970-01-01
    • 2017-03-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多