我正在处理interval
上存在其ArrayList
属性的排序start
,interval
的完整定义将在示例代码中显示为私有类。< / p>
我使用的实现是MergeSort
,与我所指的Princeton's stuff非常相似,但问题是我发现此实现仅适用于创建辅助{{ 1}}使用ArrayList aux
并使用ArrayList(Collection<? extends E> c)
对其进行初始化,尝试使用原始列表中aux.set(i, intervals.get(i));
项的相同顺序填充aux
我尝试使用interval
创建aux
并使用ArrayList(int initialCapacity)
进行初始化,但失败了。我仍然无法弄清楚为什么这种方式不起作用?
可以直接用于调试的完整代码:
aux.add(intervals.get(i))
有没有人可以帮助我理解为什么必须使用public class Test {
private class Interval {
// Will use start property to sort
int start;
int end;
Interval() {
start = 0;
end = 0;
}
Interval(int s, int e) {
start = s;
end = e;
}
@Override
public String toString() {
return "[" + start + "," + end + "]";
}
}
public void sortHelper(List<Interval> intervals) {
int len = intervals.size();
// Only this way works
List<Interval> aux = new ArrayList<Interval>(intervals);
// This way NOT work ?
//List<Interval> aux = new ArrayList<Interval>(len);
sort(intervals, aux, 0, len - 1);
}
public void sort(List<Interval> intervals, List<Interval> aux, int lo, int hi) {
if(hi <= lo) {
return;
}
int mid = lo + (hi - lo) / 2;
sort(intervals, aux, lo, mid);
sort(intervals, aux, mid + 1, hi);
mergeHelper(intervals, aux, lo, mid, hi);
}
public void mergeHelper(List<Interval> intervals, List<Interval> aux, int lo, int mid, int hi) {
// Only this way works
for(int i = lo; i <= hi; i++) {
aux.set(i, intervals.get(i));
}
// Combine with List<Interval> aux = new ArrayList<Interval>(len);
// this way NOT work ?
//for(int i = lo; i <= hi; i++) {
// aux.add(intervals.get(i));
//}
int left = lo;
int right = mid + 1;
for(int k = lo; k <= hi; k++) {
if(left > mid) {
intervals.set(k, aux.get(right++));
} else if(right > hi) {
intervals.set(k, aux.get(left++));
} else if(less(aux.get(right), aux.get(left))) {
intervals.set(k, aux.get(right++));
} else {
intervals.set(k, aux.get(left++));
}
}
}
public boolean less(Interval a, Interval b) {
return a.start - b.start < 0;
}
public static void main(String[] args) {
Test m = new Test();
Interval one = m.new Interval(1, 3);
Interval two = m.new Interval(2, 6);
Interval three = m.new Interval(8, 10);
Interval four = m.new Interval(15, 18);
List<Interval> intervals = new ArrayList<Interval>();
// Adding order as [2,6],[1,3],[8,10],[15,18]
intervals.add(two);
intervals.add(one);
intervals.add(three);
intervals.add(four);
m.sortHelper(intervals);
// Expected sort result should be
// [1,3],[2,6],[8,10],[15,18]
for(Interval i : intervals) {
System.out.println(i);
}
}
}
创建辅助ArrayList aux
并使用ArrayList<Collection<? extends E> c>
进行初始化?或者我的理解走错路?
感谢
答案 0 :(得分:1)
感谢来自@maraca和@Dukeling的重要提示,经过一些工作,以下是我对此问题的看法:
Q1 :为什么在List<Interval> aux = new ArrayList<Interval>(len);
使用aux.add(intervals.get(i));
时无效?
A1 :这里有两个主要问题,我应该承认,在array
MergeSort
new ArrayList<Interval>(len)
new Interval[len]
实施的前期工作中,我没有陷入一些习惯性的想法,这里的影响是( 1)aux[i] = intervals[i]
是否等于=
? (2)aux.add(intervals.get(i))
(仅用于解释,而不是在实际代码中使用new ArrayList<Interval>(len)
)等于ArrayList
?
对于问题(1),这里使用len = 4
的实际情况仅定义[]
大小的初始限制,但没有像空格持有者一样使用的实际项目填充到初始化列表中,例如如果我们设置[interval obj, interval obj, interval obj, interval obj]
,则初始化列表实际为new ArrayList<Interval>(len)
,而不是aux.set(i, intervals.get(i))
。假设将java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
与len
一起使用,IDE将抛出interval
,因为初始化和set方法无法在空列表中工作,因此没有真实对象填充到此列表中。此问题的解决方案是创建List<Interval> aux = new ArrayList<Interval>((Arrays.asList(new Interval(), new Interval(), new Interval(), new Interval())));
个虚拟List<Interval> aux = new ArrayList<Interval>(intervals);
个对象,以在初始化时填充列表,例如
aux.add(intervals.get(i))
,但由于我们不关心在辅助列表上首先初始化的内容,只是用作占位符,如果对象太多,上面的代码可以替换为aux[i] = intervals[i]
返回我们正确的解决方案。
对于问题(2),这里的实际案例是使用set()
不等于add()
,至少我们应该使用add()
而不是aux
,因为{{ 1}}会不断附加MergeSort
,MergeSort
不会add()
,因为aux
需要完全相同大小的辅助收藏副本来帮助排序。仍然使用相同的示例来解释使用set()
请注意,在第3次合并之后,add()
大小会增加到原始列表的两倍大小,这会在复制回原始列表时导致索引问题。但是,如果我们使用clear()
,则不会造成这种麻烦。
Q2 :如果仍想使用aux
这是正确的方法吗?
A2 :正如@Dukeling所提到的,我们需要add()
clear()
在最终回合之前从原始列表到辅助列表,例如在第3次合并发生之前在上面的例子。
以下public void mergeHelper(List<Interval> intervals, List<Interval> aux, int lo, int mid, int hi) {
aux.clear();
for(int i = 0; i < lo; i++) {
aux.add(null);
}
for(int i = lo; i <= hi; i++) {
aux.add(intervals.get(i));
}
int left = lo;
int right = mid + 1;
for(int k = lo; k <= hi; k++) {
if(left > mid) {
intervals.set(k, aux.get(right++));
} else if(right > hi) {
intervals.set(k, aux.get(left++));
} else if(less(aux.get(right), aux.get(left))) {
intervals.set(k, aux.get(right++));
} else {
intervals.set(k, aux.get(left++));
}
}
}
和{{1}}的工作代码:
{{1}}