Java 组合相交区间

Java 组合相交区间,java,algorithm,intervals,Java,Algorithm,Intervals,可能重复: 给定一个区间列表,即所有整数,如果它们相交或重叠,则应该可以将它们折叠为一个区间,否则给定的区间将不受影响。 例如,如果输入是例如I[(2-6),(1-4),(8-12)],则预期输出是[(1-6),(8-12)] e、 g.II[(4-7),(2-6),(1-4),(8-12),(7-9)]预期产量为[(1-12)] 更正:遗漏了排序部分,因此是的,这是一个O(nlogn)时间,而不是O(n)。谢谢你指出这一点。 我已经编写并测试了一个有效的O(nlogn)时间和O(2n)空间

可能重复:

给定一个区间列表,即所有整数,如果它们相交或重叠,则应该可以将它们折叠为一个区间,否则给定的区间将不受影响。 例如,如果输入是例如I[(2-6),(1-4),(8-12)],则预期输出是[(1-6),(8-12)] e、 g.II[(4-7),(2-6),(1-4),(8-12),(7-9)]预期产量为[(1-12)]

更正:遗漏了排序部分,因此是的,这是一个O(nlogn)时间,而不是O(n)。谢谢你指出这一点。 我已经编写并测试了一个有效的O(nlogn)时间和O(2n)空间算法方法。下面分享这种方法的代码。我想听听解决这个问题的不同方法,可能更有效

//假设每个间隔(2-6)等都表示为“间隔”对象(类定义如下所示),其中low=2,high=6 //步骤1:按给定间隔的低端排序 //步骤2:查找已排序区间的并集

//输入:

List<Interval> intervalList = new ArrayList<Interval>(); 
List intervalList=new ArrayList();
//输出:

List<Interval> unionList = new ArrayList<Interval>();    

private static final Comparator<Interval> Low_EPSorter = new LowEPSorter();

class Interval {
  int low, high;

  Interval(int l, int h, int m) {
    low = l;
    high = h;
  }
}
List unionList=new ArrayList();
专用静态最终比较器Low_EPSorter=新LowPSorter();
课间休息{
int低,高;
间隔(整数l,整数h,整数m){
低=l;
高=h;
}
}
////-------BEGIN:查找给定区间的并集的方法----//////

void UnionOfIntervals(){
//找到交叉点并根据需要合并间隔
int sz=intervalList.size();
//按低端排序
Collections.sort(intervalList,Low_EPSorter);
对于(int i=0;i0){
if(interval.intersect(intervalList.get(j),intervalList.get(j-1))){
区间v=union(intervalList.get(j),intervalList.get(j-1));
检查和添加(v,联合列表);
}
否则{
如果(i==1){
unionList.add(intervalList.get(j-1));
unionList.add(intervalList.get(j));
}
否则{
unionList.add(intervalList.get(j));
}
}//没有交叉路口
}//如果至少有2个元素
}
//并集后打印间隔
System.out.println(“排序后的输入间隔:”);
对于(间隔v:间隔列表){
系统输出打印(v.low+“,+v.high+”);
}
System.out.println();
System.out.println(“区间的并集:”);
对于(间隔v:联合列表){
系统输出打印(v.low+“,+v.high+”);
}
}
无效检查添加(间隔x,列表t){
int top=t.size()-1;
if(top>=0&&interval.intersect(unionList.get(top),x)){
间隔v=联合(unionList.get(顶部),x);
t、 移除(顶部);
t、 添加(v);
}
否则{
t、 加(x);
}
}
////-------END:查找给定区间并集的方法----//////

////---辅助方法--////

静态布尔相交(区间a、区间b){
布尔r=false;
如果(b.higha.high)
r=假;
否则,如果(a.低b.低)
r=1;
返回r;
}
}

如果您正在寻找一种比O(n)更有效的算法来解决这个问题,我相信您不会找到它。无论您使用什么数据结构来存储初始间隔值,最坏的情况是没有任何间隔重叠,您必须检查每个间隔以确认这一点,因此O(n)。即使有一个
HashMap
和一个非常复杂的键结构,您仍然可以看到O(n)


话虽如此,我不确定是否还有其他方法值得研究,因为您已经找到了一种算法,可以在尽可能最佳的时间O(n)内解决此问题。

只是一个想法:管理一组不相交的间隔。从空集合开始,添加传入间隔。如果新间隔与一个或两个现有间隔相交,请将它们合并。要计算交点,请使用两个树形图,参照同一组间隔,但使用不同的键:下限和上限。

另一个想法是:

  • 使用布尔数组
    • 默认情况下,将所有值设为false
    • 对于所有间隔(输入中),使值为真
    • 扫描更新后的数组并获得最终的相交结果
取一个大小为n的数组(其中n是最大的数字),分别用1和-1填充间隔开始和结束

我的意思是如果间隔是

{[1-4],[6-8]} 
那么数组元素如下所示

array[1]=1,array[4]=-1,array[6]=1,array[8]=-1
而数组的其余所有其他位置都将设置为零

现在遍历数组,通过扫描数组,我们可以得到间隔,就像这个例子一样

{[1-4],[2-5],[7-9]},
首先按照上面所述填充数组,数组A如下所示(假设起始索引为1):

现在从头遍历数组A,取变量sum=0,将存储在数组位置的值添加到sum

说明数组每个索引处的和:

位置1处:总和=1(索引1处为1)

位置2处:总和=2(索引2处为1)

位置3处:总和=2(索引3处为0)

在位置4处:总和=1(-1在索引4处)

在位置5处:总和=0(-1在索引5处)

现在总和为零,这意味着一个区间在这里结束,所以新的区间为[1-5]

位置6处:总和=0(索引6处为0)

位置7处:总和=1(索引7处为1)

(在位置7,总和再次大于零,表示间隔刚刚开始)

位置8处:总和=1(索引8处为0)

在位置9处:总和=0(-1在索引9处)

从位置7开始的间隔刚刚结束,因此新的间隔范围将是

{[1-5],[7-9]}

希望能有所帮助。

我的java体验不是最好的,但是你的原因是,java.util.Comparator)你没有编写一个运行在O(n)中的算法,而是O(n*logn),因为没有研究
{[1-4],[2-5],[7-9]},
A=[1,1,0,-1,-1,0,1,0,1]
{[1-5],[7-9]}