如何在更新后如何获取间隔树上的最大交点并获取发生间隔的时间?

时间:2019-05-03 04:14:56

标签: python algorithm data-structures

我有一组轴向对齐的矩形,我需要找到最大的相交矩形数和相交的交点(如果有多个,则任何一个或所有交点都可以)。

您可能会注意到,这个问题与https://cs.stackexchange.com/questions/18611/efficient-algorithm-for-finding-maximum-subset-of-intersecting-rectanglesMax number of overlapping rectangles这两个问题非常相似。

对于这两个问题,我正在采用类似的方法获得最佳答案。首先,我将矩形分为两部分,底部开始(开放间隔),顶部结束(结束间隔)。然后根据它们的x值对这些新段进行排序。完成此操作后,我将创建一个间隔树并开始遍历各段,如果遇到开放间隔,则将其添加到间隔树中,如果遇到结束间隔,则将其从间隔树中删除。最后,关于这两个问题的答案说:每次更新后,我必须跟踪最大的交叉点数(这是我遇到的问题)

关于这些答案,他们说跟踪每次更新后的最大路口数量将花费 O(1)时间

我想出一个解决方案的唯一方法是拥有一个数组Intervals和一个数组A,其中每个Intervals [i]都是间隔的开始或结束,而A [i]将具有计数方式许多矩形以Intervals [i]相交。这样,当添加或删除间隔时,我可以使用二进制搜索更新A和间隔,然后从新间隔的开始一直到结束更新A中的值。但这会给我一个 O(2 * log(n)+(interval_end-interval_beginning))线性解(在最坏的情况下,要添加或删除的间隔会包围所有其他间隔)。

正式说明问题:如何在O(1)或O(log(n))时间更新后获得相交的最大间隔数?

这是我在python中解决方案的代码。该函数接受开头和结尾的段并输出最大相交间隔数:

import bisect

def max_intersections(segments):
    # Segments have format ((a, b), (c, d), 'b') for open segments
    # And ((a, b), (c, d), 'e') for ending segments
    max_count = 0
    intervals = []
    A = []
    segments = sorted(segments, key=lambda x: (x[0][0], x[2])) # Process open segments first

    for segment in segments:
        if segments[2] == 'b':
            # Open segment, insert interval

            index_beginning = bisect.bisect_left(intervals, segment[0][1])
            intervals.insert(index_beginning, segment[0][1])

            index_end = bisect.bisect_right(intervals, segment[1][1])
            intervals.insert(index_end, segment[1][1])

            # Add one to all elements in A[index_beginning:index_end + 1]
            for i in range(index_beginning, index_end + 1):
                A[i] += 1
                max_count = max(A[i], max_count) # Keep track of the maximum

        else:
            # End segment, remove interval

            index_beginning = bisect.bisect_left(intervals, segment[0][1])
            index_end = bisect.bisect_right(intervals, segment[1][1])

            # Subtract one to all elements in A[index_beginning:index_end + 1]
            # Before removing the elements

            for i in range(index_beginning, index_end + 1):
                A[i] -= 1
            intervals.pop(index_end)
            intervals.pop(index_beginning)

    return max_count

代码上可能会有一些小错误,但是算法的一般逻辑就在那儿(请放手吧)。

正如您在每个步骤中看到的那样,我正在执行两个二进制搜索并遍历interval_beginning-interval_end之间的所有索引。在最坏的情况下,该间隔将包围所有其他间隔,必须经过A中的所有位置,从而给出O(N ^ 2)时间。 如何使max_intersections函数花费O(N * log(N))时间?

0 个答案:

没有答案