我们知道:
- 画布的大小
- 每个矩形的大小
- 每个矩形的位置
{ [0-8], [0-8], [9-10] }
,垂直轴上的区间集将是{ [0-3], [4-6], [0-4] }
这只是一个草图,我在这里抽象了许多细节(例如,通常人们会询问一个区间集/树“哪些区间与此重叠”,而不是“与此相交”,但没有做不到的事情)。
编辑
请观看这个相关的MIT讲座(有点长,但非常值得)。即使您找到比实现增强红黑树更简单的解决方案,也了解这些东西背后的想法是好的。O(n log n)
的时间内完成同样的事情,在实践中可能比区间树更快。 - IVlad不平行的线条将在某一点相交。计算每条线条的斜率,然后确定它们不会相交的线条。
从这里开始,让我们看看如何进行优化。我不确定您的数据是如何表示的,并且我无法查看您的图像。
使用斜率进行简单的相等性检查,这可能意味着您可以利用对数据进行排序。实际上,您可以只创建一组不同的斜率。您需要想出如何表示数据,以便不将同一矩形的两个斜率计算为相交。
编辑:等等...如果两个边界延伸到无限远的矩形没有相交,那么怎么可能?矩形基本上是两条相互垂直的线条。如果将这些线条延伸到无穷远,那么它不应该始终与另一个相交吗?
只要你没有提到你选择用哪种语言来解决问题,我将使用某种伪代码
这个想法是,如果一切正常,那么沿着一个轴排序的矩形边缘的集合应该是一系列不重叠的区间。
foreach rect in rects do
btc.insert(rect.top, rect.id)
btc.insert(rect.bottom, rect.id)
btc_item = btc.first()
do
id = btc_item.id
btc_item = btc.next()
if(id != btc_item.id)
then report_invalid_placement(id, btc_item.id)
btc_item = btc.next()
while btc_item is valid
5,7,8 - 重复步骤2、3、4,针对rect.left和rect.right坐标
O(n log n)
,在bst中插入n
项也是O(n log n)
。o(n)
,因此对于多个查询而言,bst并不比排序更好。区间树可能是,但也仅限于多个查询。do .. while
循环是 O(1)
吗? - IVlad我喜欢这个问题。这是我的尝试:
如果可能的话: 从每个矩形创建一个多边形。将每条边视为必须裁剪的最大长度线。使用裁剪算法检查一条线是否与另一条相交。例如,这个:线段裁剪
但请记住:如果您找到一个在角点位置的交点,则它是有效的。
这里有一个想法。不要使用 (x, y, width, height)
来创建每个矩形,而是使用 (x1, y1, x2, y2)
实例化它们,或者至少让它根据给定的宽度和高度解释这些值。
这样,您可以检查哪些矩形具有类似的 x
或 y
值,并确保相应的矩形具有相同的次要值。
例子:
你提供的矩形有以下数值:
首先,我们比较方块1
和方块3
(没有碰撞):
接下来,我们比较方块3
和方块4
(发生了碰撞):
嘿,将重叠区间的答案推到极致,你只需确定沿x和y轴的所有不同区间。对于每条切割线,在基于区间起始值的轴上进行上限搜索。如果找不到区间或区间与线没有交集,则它是有效的线。
稍微棘手的部分是要意识到有效的切割线不会沿着轴与矩形边界相交,因此您可以将重叠的区间合并为单个区间。最终得到一个简单的排序数组(在O(n)时间内填充)和每条切割线的O(log n)搜索。