【发布时间】:2012-09-10 17:06:01
【问题描述】:
给定一个区间列表表示所有整数,如果它们确实相交或重叠,则应该可以将它们折叠成一个区间,否则给定的区间不受影响。 比如说,如果输入是例如 I [(2-6), (1-4), (8-12)],那么预期的输出是 [(1-6), (8-12)] 例如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 and high = 6 // Step1:按给定区间的低端点排序 // Step2: 求排序区间的并集
//输入:
List<Interval> intervalList = new ArrayList<Interval>();
//输出:
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;
}
}
////-------BEGIN:找到给定区间的并集的方法----//////
void UnionOfIntervals() {
//Find intersection and combine intervals as necessary
int sz = intervalList.size();
// sort by low endpoint
Collections.sort(intervalList, Low_EPSorter);
for(int i = 0; i < sz; i++) {
int j = i;
if(j > 0) {
if( Intervals.intersect(intervalList.get(j), intervalList.get(j-1)) ) {
Interval v = union(intervalList.get(j), intervalList.get(j-1));
checkAndAdd(v, unionList);
}
else {
if(i == 1) {
unionList.add(intervalList.get(j-1));
unionList.add(intervalList.get(j));
}
else {
unionList.add(intervalList.get(j));
}
} //No intersection
} //If 2 elements atleast
}
//Print intervals after union
System.out.println("Input intervals after sorting:");
for(Interval v : intervalList) {
System.out.print(v.low + "," + v.high + " ");
}
System.out.println();
System.out.println("Union of intervals:");
for(Interval v : unionList) {
System.out.print(v.low + "," + v.high + " ");
}
}
void checkAndAdd(Interval x, List t) {
int top = t.size()-1;
if( top >=0 && Intervals.intersect(unionList.get(top), x) ) {
Interval v = union(unionList.get(top), x);
t.remove(top);
t.add(v);
}
else {
t.add(x);
}
}
////-------END:找到给定区间的并集的方法----//////
////--- 辅助方法--- ////
static boolean intersect(Interval a, Interval b) {
boolean r = false;
if(b.high < a.low || b.low > a.high)
r = false;
else if(a.low <= b.high && b.low <= a.high)
r = true;
return r;
}
Interval union(Interval a, Interval b) {
int l = (a.low < b.low) ? a.low : b.low;
int max = (a.high > b.high) ? a.high : b.high;
return new Interval(l, max);
}
private static class LowEPSorter implements Comparator<Interval> {
public int compare(Interval a, Interval b) {
int r = 0;
if(a.low < b.low)
r = -1;
else if(a.low > b.low)
r = 1;
return r;
}
}
【问题讨论】:
-
我的 java 体验不是最好的,但是由于docs.oracle.com/javase/1.4.2/docs/api/java/util/…, java.util.Comparator) 你还没有编写在 O(n) 中运行的算法,但是 O(n *登录 n) 代替
-
-1 表示在输入此问题时未研究且未注意 SO 提供的建议重复项。这已在 SO 上多次回答
-
可以在 O(n) 中求解,但区间中的最高数应与 n 相当。
-
@AkashdeepSaluja:可以在 O(n) 中解决,如果选择基于非比较的排序,如计数排序,输入中最高数字的知识有帮助?
-
@sangv 是的,可以说这个想法基本上是计数排序,但不完全是。我也发布了我的建议作为答案。