【问题标题】:Count number of intervals containing another interval?计算包含另一个间隔的间隔数?
【发布时间】:2016-05-17 19:47:50
【问题描述】:

给定两个列表,每个列表包含 N 个区间(数轴的子集),每个区间都有起点和终点的形式。一个列表中有多少对这些区间包含另一个列表中的区间?

例如:

如果列表 A 是 {(1,7), (2,9)} 而列表 B 是 {(3,6), (5,8)}

那么 A 的区间包含 B 中的区间的对数将是 3 对:

(1,7),(3,6)
(2,9)(3,6)
(2,9)(5,8)

目标是为 O(n log n) 射击。

我目前的算法是先按 x 坐标排序并将其作为一个列表。然后按 y 坐标对列表进行排序,并计算两个列表之间的倒数。但我的问题是为什么这行得通?任何见解将不胜感激。

我目前的可视化方式是以下几何方式(其中每条线的交点都是 num 反转的计数):

注意:我不确定如何检查列表列表中的反转。只是试图获得一种可以给出 O(n log n) 的方法。如果有任何其他方法很乐意听取建议。

【问题讨论】:

    标签: algorithm optimization intervals divide-and-conquer inversion


    【解决方案1】:

    如果您决定也尝试树/网格方法,我将解释它是如何工作的。对于您的任务,您不需要 2D,而是需要一维区间图甚至网格。让我们选择网格,因为它更清晰。

    假设您的对是从 1 到 100 的整数。那么您可以拥有一个大小为 100 的数组。数组中的每个单元格都包含空集(有序列表)。见下图:

    现在我们开始在网格中添加间隔。我们在 1,7 和 2 之间的所有网格单元格中添加 1,在 2,9 之间的所有网格单元格中添加 1(1,2 是 ID,我们在每个插入间隔增加 1,以这种方式插入效率低,但可以修复)。

    现在我们如何检查 B 的间隔?我们只是从第一个单元格中获取每个 ID 并检查它是否也在第二个单元格中。由于单元格是集合,因此检查需要 O(log n)。在最坏的情况下,我们需要 n O(log n) 次操作来检查来自 B 的一个区间在 A 内部的重叠区间计数。

    这可以扩展为使用区间图而不是网格(如果数字不是小整数)。此外,如果您在 A 中有固定数量的间隔,并且没有内存要求,例如,如果我们将集合替换为数组,O(logN) 可能会变为 O(1)。

    【讨论】:

    • 不使用树形结构可以实现吗?
    • 是的。这就是想法。您可以使用“间隔”而不是点。首先尝试在一维中找出它。取而代之的是二叉树(集合),您可以制作 interval_tree。然后可以使用这棵树在 logN 中找到一个点所属的区间。
    • 对不起,我没有正确阅读您的问题不在于 2D 中的 (x,y) 点。你不需要四叉树。
    【解决方案2】:

    我将回答第一个问题,即为什么反转解决方案有效。首先,我要澄清一件事。您不应该计算所有反转(线的交叉点),而只计算发生在 A 列表中的元素和 B 列表中的元素之间的那些。在您的示例中没有区别,但我们假设A = {(1,7), (2,5)}B = {(3,6), (5,8)}。如果我们在您的示例中将这些情况可视化,则会有 2 个交集,但我们正在寻找的只有一对,即 (1,7)、(3,6)。

    现在假设我们有 2 个区间:I1=(x1,y1)I2=(x2,y2)I2 包含在 I1 中。这意味着x1 <= x2y1 >= y2。现在,如果您按 x 对区间列表进行排序,那么 I1 将始终位于 I2 之前。类似地,如果您按 y 对区间列表进行排序,那么I1 将始终位于I2 之后。如果我们将第一个列表中的I1I2 与第二个列表中的I1I2 连接起来,那么这些线必须交叉。

    但是,我们假设x1 <= x2y1 < y2。现在I1 将在第一个和第二个列表中的I2 之前。如果我们将第一个列表中的I1I2 与第二个列表中的I1I2 连接起来,那么这些线将永远不会交叉。同样的情况是如果x1 > x2y1 >= y2

    以下是这些案例的可视化:

    【讨论】:

      猜你喜欢
      • 2012-03-26
      • 1970-01-01
      • 2022-11-22
      • 2021-08-21
      • 1970-01-01
      • 2014-02-18
      • 2017-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多