Algorithm 区间树中的最大非重叠区间

Algorithm 区间树中的最大非重叠区间,algorithm,interval-tree,Algorithm,Interval Tree,给定一个时间间隔列表,我需要找到一组最大不重叠的时间间隔 比如说, 如果我们有以下时间间隔: [0600, 0830], [0800, 0900], [0900, 1100], [0900, 1130], [1030, 1400], [1230, 1400] 此外,还规定时间必须在[0000,2400]范围内 最大不重叠的间隔集是[06000830]、[09001130]、[12301400] 我知道最大集合包装是NP完全的。我想确认我的问题(区间仅包含开始和结束时间)是否也是NP完全问题

给定一个时间间隔列表,我需要找到一组最大不重叠的时间间隔

比如说,

如果我们有以下时间间隔:

[0600, 0830], [0800, 0900], [0900, 1100], [0900, 1130], 
[1030, 1400], [1230, 1400]
此外,还规定时间必须在
[0000,2400]
范围内

最大不重叠的间隔集是
[06000830]、[09001130]、[12301400]

我知道最大集合包装是NP完全的。我想确认我的问题(区间仅包含开始和结束时间)是否也是NP完全问题


如果是这样的话,有没有一种方法可以在指数时间内找到一个最优的解决方案,但需要更智能的预处理和修剪数据。或者如果有一个相对容易实现的固定参数可处理算法。我不想使用近似算法。

这不是一个NP完全问题。我可以想出一个
O(n*log(n))
算法,使用动态规划来解决这个问题

假设我们有n个区间。假设给定的范围是
S
(在您的例子中,
S=[0000,2400]
)。假设所有间隔都在
S
范围内,或者在线性时间内消除所有不在
S
范围内的间隔

  • 预处理:

    • 按开始点对所有间隔进行排序。假设我们得到一个间隔为n的数组
      A[n]
      • 此步骤需要
        O(n*log(n))
        时间
    • 对于区间的所有终点,找到其后面最小起点的索引。假设我们得到一个由
      n
      整数组成的数组
      Next[n]
      • 如果间隔
        i的终点不存在这样的起点,
        我们可以将
        n
        分配给
        Next[i]
      • 我们可以在
        O(n*log(n))
        时间中通过枚举所有间隔的n个端点来完成此操作,并使用二进制搜索来找到答案。也许有线性方法可以解决这个问题,但这并不重要,因为前面的步骤已经花费了
        O(n*log(n))
        时间
  • DP:

    • 假设范围
      [A[i].开始,S.end]
      中的最大非重叠间隔为
      f[i]
      。那么
      f[0]
      就是我们想要的答案
    • 也假设f[n]=0
    • 状态转移方程:
      • f[i]=max{f[i+1],1+f[Next[i]}
    • 很明显,DP步骤需要线性时间
  • 上面的解决方案就是我第一眼看到这个问题时想到的。在那之后,我还想到了一种更简单的贪婪方法(但在大O符号的意义上不是更快):

    (采用与上述DP方法相同的符号和假设)

  • 预处理:按结束点对所有间隔进行排序。假设我们得到一个n个间隔的数组
    B[n]

  • 贪婪的:

    int ans = 0, cursor = S.begin;
    for(int i = 0; i < n; i++){
        if(B[i].begin >= cursor){
            ans++;
            cursor = B[i].end;
        }
    }
    
    intans=0,cursor=S.begin;
    对于(int i=0;i=光标){
    ans++;
    游标=B[i]。结束;
    }
    }
    
  • 以上两种解决方案出自我的想法,但你的问题也被称为活动选择问题,可以在维基百科上找到


    此外,《算法导论》在16.1中深入讨论了这个问题。

    最大值是指间隔的最大数量还是间隔的总持续时间最长?您的示例解决方案是3次间隔,总持续时间为6.5小时。是什么使它最大,3还是6.5?我对第一点的第二点有点困惑。你是说我们需要为下一个可能的间隔创建一个新数组吗?这就是
    Next[n]
    是什么,还是
    Next[n]==A[n]
    ?也许你可以写更多的代码来澄清?