Algorithm 按时间间隔合并范围
给定一组区间:{1-4,6-7,10-12}添加一个新区间:(9,11),以便最终的解“合并”:输出:{1-4,6-7,9-12}。合并可以在双方进行(低范围和高范围) 我看到这个问题在多个地方得到了回答,有人甚至建议使用间隔树,但没有解释他们将如何使用它。我所知道的唯一解决方案是按照开始时间的升序排列时间间隔,并对其进行迭代,并尝试适当地合并它们 如果有人能帮助我理解我们如何在这个用例中使用区间树,那就太好了Algorithm 按时间间隔合并范围,algorithm,merge,tree,range,interval-tree,Algorithm,Merge,Tree,Range,Interval Tree,给定一组区间:{1-4,6-7,10-12}添加一个新区间:(9,11),以便最终的解“合并”:输出:{1-4,6-7,9-12}。合并可以在双方进行(低范围和高范围) 我看到这个问题在多个地方得到了回答,有人甚至建议使用间隔树,但没有解释他们将如何使用它。我所知道的唯一解决方案是按照开始时间的升序排列时间间隔,并对其进行迭代,并尝试适当地合并它们 如果有人能帮助我理解我们如何在这个用例中使用区间树,那就太好了 [我一直在关注CLRS书中的间隔树,但它们并没有讨论合并,它们只讨论插入和搜索。]查
[我一直在关注CLRS书中的间隔树,但它们并没有讨论合并,它们只讨论插入和搜索。]查看此内容。它可以帮助您: 图书馆提供以下功能: 1) 区间集 2) 分离间隔集 3) 分割间隔集(我假设这意味着间隔不能重叠,否则它们会被合并。) 实现这一点的一种方法是存储一个平衡的二叉搜索树,每个范围的端点有一个节点。然后,每个节点将被标记为一个“打开”节点(标记间隔的开始)或一个“关闭”节点(标记间隔的结束) 插入新范围时,将出现两种情况之一,即范围的起点:
希望这有帮助 只需将相关的间隔添加到间隔集的末尾,然后对间隔集的所有元素执行合并即可 此处详细介绍了合并操作:
如果你没有心情C++代码,Python中的内容也一样:
def mergeIntervals(self, intervalSet):
# interval set is an array.
# each interval is a dict w/ keys: startTime, endTime.
# algorithm from: http://www.geeksforgeeks.org/merging-intervals/
import copy
intArray = copy.copy(intervalSet)
if len(intArray) <= 1:
return intArray
intArray.sort(key=lambda x: x.get('startTime'))
print "sorted array: %s" % (intArray)
myStack = [] #append and pop.
myStack.append(intArray[0])
for i in range(1, len(intArray)):
top = myStack[0]
# if current interval NOT overlapping with stack top, push it on.
if (top['endTime'] < intArray[i]['startTime']):
myStack.append(intArray[i])
# otherwise, if end of current is more, update top's endTime
elif (top['endTime'] < intArray[i]['endTime']):
top['endTime'] = intArray[i]['endTime']
myStack.pop()
myStack.append(top)
print "merged array: %s" % (myStack)
return myStack
公共类合并间隔{
public static class Interval {
public double start;
public double end;
public Interval(double start, double end){
this.start = start;
this.end = end;
}
}
public static List<Interval> mergeInteval(List<Interval> nonOverlapInt, Interval another){
List<Interval> merge = new ArrayList<>();
for (Interval current : nonOverlapInt){
if(current.end < another.start || another.end < current.start){
merge.add(current);
}
else{
another.start = current.start < another.start ? current.start : another.start ;
another.end = current.end < another.end ? another.end : current.end;
}
}
merge.add(another);
return merge;
}
公共静态类间隔{
公共双启动;
公共双端;
公共间隔(双起点、双终点){
this.start=start;
this.end=end;
}
}
公共静态列表mergeInteval(列表非重叠,间隔另一个){
列表合并=新建ArrayList();
用于(间隔电流:非重叠点){
if(current.end
C#
公共类间隔
{
公共间隔(int start,int end){this.start=start;this.end=end;}
公共int启动;
公共互联网终端;
}
void AddInterval(列表、间隔)
{
int-lo=0;
inthi=0;
对于(lo=0;lo=list[lo]。start&&interval.start=list[hi]。start&&interval.end 0)
{
列表.拆卸范围(lo+1,hi-lo);
}
}
谢谢,但我更感兴趣的是算法,而不是现成的库/API。一个简单的算法可能是,您可以首先通过起始值对范围进行排序,然后从头到尾迭代范围,每当您发现一个范围与下一个重叠时,将其合并。是的,我已经知道了。引用根据我的问题:“我所知道的唯一解决方案是按照间隔开始时间的升序排列间隔,并对其进行迭代,并尝试将其适当合并。”。我正在寻找一个更优化的解决方案(可能涉及间隔树?)这个答案:提到了合并间隔树的算法对于起始点插入情况:首先检查具有
public static class Interval {
public double start;
public double end;
public Interval(double start, double end){
this.start = start;
this.end = end;
}
}
public static List<Interval> mergeInteval(List<Interval> nonOverlapInt, Interval another){
List<Interval> merge = new ArrayList<>();
for (Interval current : nonOverlapInt){
if(current.end < another.start || another.end < current.start){
merge.add(current);
}
else{
another.start = current.start < another.start ? current.start : another.start ;
another.end = current.end < another.end ? another.end : current.end;
}
}
merge.add(another);
return merge;
}
public class Interval
{
public Interval(int start, int end) { this.start = start; this.end = end; }
public int start;
public int end;
}
void AddInterval(List<Interval> list, Interval interval)
{
int lo = 0;
int hi = 0;
for (lo = 0; lo < list.Count; lo++)
{
if (interval.start < list[lo].start)
{
list.Insert(lo, interval);
hi++;
break;
}
if (interval.start >= list[lo].start && interval.start <= list[lo].end)
{
break;
}
}
if (lo == list.Count)
{
list.Add(interval);
return;
}
for (hi = hi + lo; hi < list.Count; hi++)
{
if (interval.end < list[hi].start)
{
hi--;
break;
}
if (interval.end >= list[hi].start && interval.end <= list[hi].end)
{
break;
}
}
if (hi == list.Count)
{
hi = list.Count - 1;
}
list[lo].start = Math.Min(interval.start, list[lo].start);
list[lo].end = Math.Max(interval.end, list[hi].end);
if (hi - lo > 0)
{
list.RemoveRange(lo + 1, hi - lo);
}
}