我有一组轴向对齐的矩形,我需要找到最大的相交矩形数和相交的交点(如果有多个,则任何一个或所有交点都可以)。
您可能会注意到,这个问题与https://cs.stackexchange.com/questions/18611/efficient-algorithm-for-finding-maximum-subset-of-intersecting-rectangles和Max 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))时间?