【问题标题】:Filtering out list elements with O(n) time complexity过滤掉具有 O(n) 时间复杂度的列表元素
【发布时间】:2014-07-20 00:12:36
【问题描述】:

我有一个元素列表,其中每个元素都是一个非负整数范围。我想过滤列表,以便只分离出最大的未封闭范围。我想以O(n) 的方式使用单循环执行此操作。此列表将始终根据每个范围的起始整数进行排序。封闭的范围元素可能出现在列表中的封闭范围元素之前或之后。

示例:

假设我拥有的列表是{[0-12],[5-15],[5-20],[10-20],[11-30],[25-42],[28-40]}。在此列表中,[5-15][10-20] 范围在 [5-20] 范围内,因此我需要丢弃它们。类似地,范围元素[28-40] 被丢弃,因为它落在范围[25-42] 内。 我想使用单个循环进行此过滤以实现O(n) 时间复杂度。

有可能做到这一点吗?如果不是,那么比O(n) 更复杂的过滤的最佳方法是什么。 Java中的解决方案会很棒。

【问题讨论】:

  • 您对列表呈现给您的顺序有什么保证-在您的示例中,它是由start, end排序的-总是这样吗?你想对部分重叠的范围做什么,例如1-6, 3-8
  • 使用Interval Tree保证O(nlogn)。
  • 假设它们按起始值排序,您可以执行 O(n),我合并重叠的连续范围。当它们不再重叠时,您将继续下一个。
  • 好吧,一旦合并,这些范围实际上会以一个 0-42 大范围结束,对吧?这就是你要找的东西吗?

标签: java algorithm sorting data-structures


【解决方案1】:

如果一个元素具有相同的起点范围但更大或相等的终点,则它们可能会吞噬前一个元素。如果下一个范围的结束小于当前元素的结束,则该元素可能会吞下下一个。

因此,您浏览列表并比较当前和下一个元素。

如果他们有 currentStart=nextStart 和 nextEnd>=currentEnd -> 删除当前。

else If nextEnd 删除下一个。

【讨论】:

  • 提供一个简短的正确性证明可能会有所帮助。
【解决方案2】:

在伪代码中,合并周期可以这样完成:

def merge(l:list[period], e:period):
    if l == nil:
        return list(e)
    else:
        lh = l.head
        ll = l.tail
        if e.end < lh.start: 
            return e::l // original list prepended with e
        else if lh.end < e.start:
            return lh::merge(e,ll) // head + trying to merge period with the tail
        else: //overlap, make new period from e and list head and merge it with tail
            newstart = min(e.start, lh.start)
            newend = max(e.end, lh.end)
            return merge(period(newstart,newend), ll)

在你的情况下,你必须区分 i/o 合并,但想法是相似的。

【讨论】:

    猜你喜欢
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 2013-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多