Possible Interview Question: How to Find All Overlapping Intervals =>为我们提供找到所有重叠间隔的解决方案。除了这个问题,想象每个间隔都有一个权重。当插入新的间隔时,我的目标是找到重叠间隔加总的权重。
条件:新插入的区间的结束值总是大于先前插入的区间的终点,这将导致我们已经排序了终点。
当插入新的间隔及其重量时,应检查所有重叠的间隔加总重量是否超过限制。例如,当我们插入[15, 70] 2
时,[15, 20]
的总和权重将为130,并且它应该给出错误,因为它超过了限制= 128,否则新插入的间隔将附加到列表中。
int limit = 128;
Inserted itervals in order:
order_come | start | end | weight
0 [10, 20] 32
1 [15, 25] 32
2 [5, 30] 32
3 [30, 40] 64
4 [1, 50] 16
5 [1, 60] 16
6 [15, 70] 2 <=should not append to the list.
Final overall summed weight view of the List after `[15, 70] 2` is inserted:
[60, 70, 2]
[50, 60, 18]
[40, 50, 34]
[30, 40, 98]
[25, 30, 66]
[20, 25, 98]
[15, 20, 130] <= exceeds the limit=128, throw an error.
[10, 15, 96]
[5, 10, 64]
[1, 5, 32]
[0, 0, 0]
感谢您宝贵的时间和帮助。
答案 0 :(得分:2)
O(log n)-time插入可以使用扩充二进制搜索树。存储
order_come | start | end | weight
0 [10, 20] 32
1 [15, 25] 32
2 [5, 30] 32
3 [30, 40] 64
4 [1, 50] 16
5 [1, 60] 16
我们有一棵形状像
的树 25
/ \
/ \
10 50
/ \ / \
5 20 40 60
/ / /
1 15 30 ,
其中每个数字代表从它到其后继的间隔。与每个树节点相关联的是两个数字。第一个我们称为Δweight,定义为节点间隔的权重减去节点的父节点的权重,如果是范围(否则为零)。第二个我们称为Δmax,定义为对应于节点后代的区间的最大权重,减去节点的权重。
对于上面的例子,
interval | tree node | total weight | ∆weight | ∆max
[1, 5) 1 32 -32 0
[5, 10) 5 64 -32 0
[10, 15) 10 96 32 32
[15, 20) 15 128 32 0
[20, 25) 20 96 0 32
[25, 30) 25 64 64 64
[30, 40) 30 96 64 0
[40, 50) 40 32 16 64
[50, 60) 50 16 -48 80
[60, ∞) 60 0 -16 0
二进制搜索树操作几乎总是需要轮换。当我们旋转像
这样的树时 p c
/ \ / \
c r => l p
/ \ / \
l g g r
我们修改
c.∆weight += p.∆weight
g.∆weight += c.∆weight
g.∆weight -= p.∆weight
p.∆weight -= c.∆weight
p.∆max = max(0, g.∆max + g.∆weight, r.∆max + r.∆weight)
c.∆max = max(0, l.∆max + l.∆weight, p.∆max + p.∆weight).
增强的重点如下。要在树中查找最大权重,请计算r.∆max + r.∆value
,其中r
是根。要通过给定数量∂增加子树中的每个权重,请将子树根的Δweight增加∂。通过使用包含 - 排除更改O(log n)节点,我们可以增加整个间隔。总之,这些操作允许我们评估插入时间O(log n)。
要查找间隔的总重量,请搜索该间隔正常,同时还要将该间隔的祖先的Δweight值相加。例如,为了找到[15,30]的权重,我们寻找15,遍历25(Δweight= 64),10(Δweight= 32),20(Δweight= 0)和15(Δweight= 32),总重量为64 + 32 + 0 + 32 = 128。
要在假设的时间间隔内找到最大总重量,我们会进行修改后的搜索。使用另一个修改后的搜索,计算小于或等于start
的最大树值(predstart
;如果predstart = -∞
所有树值都大于start
,则允许start
})并将其传递给此maxtotalweight
。
maxtotalweight(root, predstart, end):
if root is nil:
return -∞
if end <= root.value:
return maxtotalweight(root.leftchild, predstart, end) + root.∆weight
if predstart > root.value:
return maxtotalweight(root.rightchild, predstart, end) + root.∆weight
lmtw = maxtotalweight1a(root.leftchild, predstart)
rmtw = maxtotalweight1b(root.rightchild, end)
return max(lmtw, 0, rmtw) + root.∆weight
maxtotalweight1a(root, predstart):
if root is nil:
return -∞
if predstart > root.value:
return maxtotalweight1a(root.rightchild, predstart) + root.∆weight
lmtw = maxtotalweight1a(root.leftchild, predstart)
return max(lmtw, 0, root.rightchild.∆max + root.rightchild.∆weight) + root.∆weight
maxtotalweight1b(root, end):
if root is nil:
return -∞
if end <= root.value:
return maxtotalweight1b(root.leftchild, end) + root.∆weight
rmtw = maxtotalweight1b(root.rightchild, end)
return max(root.leftchild.∆max + root.leftchild.∆weight, 0, rmtw) + root.∆weight
我们假设nil具有Δweight= 0和Δmax=-∞。对不起所有遗漏的细节。
答案 1 :(得分:1)
时使用original answer的术语
'1E 2E 3E ... (n-1)E nE'
终点已经排序,你的(n + 1)st终点比所有先前的终点都要大,你只需要找到终点值大于(n + 1)st起点的区间(如果是封闭的间隔,则大于或等于。)
换句话说 - 迭代从最右端点到左边的间隔,直到达到端点小于或等于(n + 1)st起点的间隔并跟踪权重之和。然后检查总和是否符合限制。当所有先前的区间都具有终点格式,然后是(n + 1)个起始点时,最坏情况时间复杂度为O(n)。