如何查找所有重叠间隔总和权重?

时间:2017-02-08 14:19:44

标签: algorithm

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.

enter image description here

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]

感谢您宝贵的时间和帮助。

2 个答案:

答案 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)。