间隔的联盟间隔的联盟(Union of intervals)

2019-05-13 16:33发布

我有表示间隔一类。 这个类有两个属性“开始”和类似类型的“结束”。 现在,我在寻找一个有效的算法取一组这样的区间的联合。

提前致谢。

Answer 1:

用术语(启动,例如)的一个排序,然后检查其(右)邻居重叠,你在列表中移动。

class tp():
    def __repr__(self):
        return '(%d,%d)' % (self.start, self.end)
    def __init__(self,start,end): 
        self.start=start
        self.end=end
s=[tp(5,10),tp(7,8),tp(0,5)]
s.sort(key=lambda self: self.start)
y=[ s[0] ]
for x in s[1:]:
  if y[-1].end < x.start:
      y.append(x)
  elif y[-1].end == x.start:
      y[-1].end = x.end


Answer 2:

使用扫描线算法。 基本上,你所有的排序列表中的值(同时保持它无论是开始或间隔结束以及每个项目)。 这种操作是O(n log n)的。 然后你在沿着分类项的单次循环和计算区间为O(n)。

为O(n log n)的+ O(n)的= O(N log n)的



Answer 3:

通过geocar算法时失败:

s=[tp(0,1),tp(0,3)]

我不是很肯定,但我认为这是正确的做法:

class tp():
    def __repr__(self):
        return '(%.2f,%.2f)' % (self.start, self.end)
    def __init__(self,start,end): 
        self.start=start
        self.end=end
s=[tp(0,1),tp(0,3),tp(4,5)]
s.sort(key=lambda self: self.start)
print s
y=[ s[0] ]
for x in s[1:]:
    if y[-1].end < x.start:
        y.append(x)
    elif y[-1].end == x.start:
        y[-1].end = x.end
    if x.end > y[-1].end:
        y[-1].end = x.end
print y

我也实现了它的减法:

#subtraction
z=tp(1.5,5) #interval to be subtracted
s=[tp(0,1),tp(0,3), tp(3,4),tp(4,6)]

s.sort(key=lambda self: self.start)
print s
for x in s[:]:
    if z.end < x.start:
        break
    elif z.start < x.start and z.end > x.start and z.end < x.end:
        x.start=z.end
    elif z.start < x.start and z.end > x.end:
        s.remove(x)
    elif z.start > x.start and z.end < x.end:
        s.append(tp(x.start,z.start))
        s.append(tp(z.end,x.end))
        s.remove(x)
    elif z.start > x.start and z.start < x.end and z.end > x.end:
        x.end=z.start
    elif z.start > x.end:
        continue

print s


Answer 4:

事实证明,这个问题已经解决,许多倍-在花哨的不同级别,根据命名(S)打算: http://en.wikipedia.org/wiki/Interval_tree , http://en.wikipedia.org /维基/ Segment_tree ,也是'RangeTree'

(如OP的问题涉及到时间间隔的大计数这些数据结构问题)


在我自己的Python库选择的选择方面:

  • 从测试中,我发现大多数钉子它的是全功能和python当前(非位腐烂)项:“间隔”和“联盟”类从SymPy,请参阅: HTTP://sympystats.wordpress。 COM / 2012/03/30 /简化套/

  • 另一个好找的选择,更高的性能,但较少的功能丰富的选项(如浮点范围去除没有工作。): https://pypi.python.org/pypi/Banyan

最后:搜索周围的SO本身,在任何IntervalTree,线段树,RangeTree的,你会找到答案/钩进一步嘉豪



Answer 5:

排序的所有点。 然后通过列表增加了“启动”点计数器,递减它“结束”点。 如果计数器为0,那么它确实是在工会的间隔之一的端点。

计数器将永远不会否定,并会在列表的最后达到0。



Answer 6:

要查找总在C区间的工会++

#include <iostream>
#include <algorithm>

struct interval
{
    int m_start;
    int m_end;
};

int main()
{
    interval arr[] = { { 9, 10 }, { 5, 9 }, { 3, 4 }, { 8, 11 } };

    std::sort(
        arr,
        arr + sizeof(arr) / sizeof(interval),
        [](const auto& i, const auto& j) { return i.m_start < j.m_start; });

    int total = 0;
    auto current = arr[0];
    for (const auto& i : arr)
    {
        if (i.m_start >= current.m_end)
        {
            total += current.m_end - current.m_start;
            current = i;
        }
        else if (i.m_end > current.m_end)
        {
            current.m_end = i.m_end;
        }
    }

    total += current.m_end - current.m_start;
    std::cout << total << std::endl;
}


文章来源: Union of intervals