O(nlogn)算法用于查找包含其他范围的范围

时间:2015-10-02 05:30:27

标签: algorithm

如果您有n个范围类似于[1,4.5]的范围,那么如何在O(nlogn)时间内找到任何索引是否包含另一个索引?注意:如果[x,y][a,b]x >= a将完全包含b <= y

这似乎可以与合并排序类似地进行,您可以检查是否有任何范围在范围总量的每一半中包含另一个范围,然后比较任一半中的任何范围是否包含另一半的范围。我的问题是,我无法找到O(n)方法来完成最后一部分。我猜我会以某种方式将某些范围结合起来,但我无法想到如何。

1 个答案:

答案 0 :(得分:10)

这是一个简单的算法,似乎在O(nlogn)时间内运行:

首先排序 n范围的集合,使用范围的开始值,从最小到最大。如果您在此处使用合并排序,则应在O(nlogn)时间内运行。正如@Aivean指出的那样,当两个或多个范围具有相等的起始值时,需要考虑一个边缘情况。在这种情况下,此类范围应按降序顺序的范围结束值排序。

接下来沿着这组范围从最小的第一个值到最高值,并执行以下操作:

for (range r : ranges[1 to N-1]) {
    if (end value for range r+1 <= end value for range r) {
        // then range r+1 is completely contained within some previous range
        return true;
    }
}

第二步是单O(n)次传递,不会改变第一步的整体O(nlogn)运行时间。

这是一个图形说明,显示算法如何工作。范围已使用范围的开始值进行排序,从最小到最大。应该清楚的是,所有必要的是从左向右走,并按顺序比较每对范围的结束值。

1. |------|
2.  |-------|
3.    |-------|
4.    |------|
5.              |-------|
6.                  |-------|

感谢在检查范围#3时我们需要检查超出范围#2的任何东西。这样做的原因是,为了使范围#1包含范围#3,它必须将扩展到范围#2之外,这意味着它已经包含范围#2。但这意味着算法已经返回true,因此我们不需要检查这种可能性。

另请注意,范围#3和#4按其结束值按降序排序。这确保算法将检测范围#4完全包含在范围#3内。您可以颠倒范围#3和#4的顺序,以查看在起始值为平局的情况下可能存在问题。