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]
- 我们可以在
时间中通过枚举所有间隔的n个端点来完成此操作,并使用二进制搜索来找到答案。也许有线性方法可以解决这个问题,但这并不重要,因为前面的步骤已经花费了O(n*log(n))
时间O(n*log(n))
- 如果间隔
- 假设范围
中的最大非重叠间隔为[A[i].开始,S.end]
。那么f[i]
就是我们想要的答案f[0]
- 也假设f[n]=0李>
- 状态转移方程:
f[i]=max{f[i+1],1+f[Next[i]}
- 很明显,DP步骤需要线性时间
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]
?也许你可以写更多的代码来澄清?