假设我有两个间隔,
[a1, a2] and [b1, b2]
a1,a2,b1,b2
都在[0, 2 pi]
范围内。现在,给定这两个间隔,我想找到它们的重叠间隔。这很棘手。因为两个间隔的例子是
[5, 1] and [0, 6]
下面是哪个草图(红色区域是间隔)。
请注意,这两个间隔返回一个由两个间隔组成的重叠间隔:
[0,1] and [5,6]
必须处理多种不同的情况,有没有已知的算法可以这样做?
答案 0 :(得分:1)
我不知道现有的算法(这并不意味着没有),但是我想出了一个。
正如@Michael Kenzel所提到的那样,数字不会单调增加,这使一切变得非常复杂。
但是我们可以观察到可以将圆圈展开到数字线上。 然后每个间隔以2π的周期无限次出现。
首先让我们定义 normalize 操作,如下所示:
normalize([a, b]):
if (a > b):
a -= 2π
使用此操作,我们将两个间隔都展开到数字线的[-2π,2π]部分。
示例间隔:
[2,5]-> [2,5]
[4,π]-> [-2,π]
一个圆上的两个间隔最多可以重叠2次。
(我对此没有适当的证明,但是凭直觉:在一个间隔开始但另一个没有结束的地方开始重叠。在数字行上只能发生一次,在我们的情况下只能发生两次。)>
仅查看归一化的时间间隔,我们可能会错过重叠部分之一。在上面的示例中,我们将检测到[2,π]重叠并且未命中[4,5]。发生这种情况是因为我们没有将原始间隔展开到[0,2π]上,而是展开了数字线[-2π,2π]的两倍长的部分。
为此,纠正,例如,我们可以将落在负线上的部分移到右边,然后将其向右移动2π,这样所有部分都在原始[0, 2π]。但这在计算上是无效的,因为在最坏的情况下,我们将不得不在一个间隔中测试2个部分,而在另一个间隔中测试2个部分,总共需要进行4次操作。
这里是一个不幸的例子的说明,该例子需要进行4次比较:
如果我们想提高效率,我们将尝试仅执行2个interval-vs-interval操作。我们将不需要更多,因为最多会有2个重叠。 由于间隔在数字线上以2π的周期无限重复,因此我们可以将第一个间隔的2个相邻重复项与第二个间隔进行比较。 为了确保第二个间隔介于两个重复之间,我们可以取一个较早开始的间隔,并在其两端加2π。或者从稍后开始的2π中减去2π。
最多会有两个重叠,然后可以通过加/减2π将其带回到[0,2π]区间。
在我们原始的示例中,它看起来像是:
总结一下:
given [a, b], [c, d]
[A, B] = normalize([a, b])
[C, D] = normalize([c, d])
if (A < C):
[E, F] = [A + 2π, B + 2π]
else:
[E, F] = [A - 2π, B - 2π]
I_1 = intersect([A, B], [C, D])
I_2 = intersect([E, F], [C, D])
bring I_1 and I_2 back to the [0, 2π]
我认为我没有错过任何极端情况,但是可以随时指出我的逻辑中的任何错误。
答案 1 :(得分:0)
只要您有一个间隔,使数字单调增加,就很简单;您只需采用最小值的max()
和最大值的min()
就可以了。这似乎是造成问题复杂化的主要根源,因为您可以让间隔环绕在0周围,也就是说,间隔中的数字并不会单调增加。在我看来,解决该问题的一种方法是简单地将环绕的间隔视为一个间隔而不是两个间隔的并集。例如,将[5,1]视为[5,2 pi]∪[0,1]。然后,找到[5,1]和[0,6]的交集的问题变成了找到[5,2 pi]和[0,6]的交集以及[0,1的交集的问题]和[0,6]。在数学上,您将利用distributive law of set intersection的优势,即(A A B)∩C =(A∩C)∪(B∩C)。因此,给定两个间隔A和B,我们首先将其分为两个间隔A1和A2以及B1和B2,其中A1和B1分别在0以后开始并在2 pi之前结束,而A2和B2在2 pi之前开始并且在2点之前结束。像这样分割,我们可以像这样计算交点
(A1∪A2)∩(B1∪B2)=(A1∩(B1∪B2))∪(A2∩(B1∪B2)=(A1∩B1)∪(A1∩B2)∪(A2∩B1 )∪(A2∩B2)
即计算A1,A2,B1和B2的所有组合的交点……