[英]MergeSort on ArrayList only work with ArrayList(Collection<? extends E> c) not ArrayList(int initialCapacity)?
I am working on sort interval
which exist on an ArrayList
with its start
property, the full definition of interval
will show in sample code as private class. 我排序工作
interval
,其存在于一个ArrayList
,其start
性能,充分定义interval
将显示在示例代码为私有类。
The implementation I am using is MergeSort
, and very similar to Princeton's stuff which I refer to, but problem is I find this implementation only work with creating auxiliary ArrayList aux
with ArrayList(Collection<? extends E> c)
and initialize it with aux.set(i, intervals.get(i));
我正在使用的实现是
MergeSort
,与我引用的普林斯顿大学的东西非常相似,但是问题是我发现此实现仅适用于使用ArrayList(Collection<? extends E> c)
创建辅助ArrayList aux
并使用aux.set(i, intervals.get(i));
对其进行初始化aux.set(i, intervals.get(i));
which try to fill aux
with same order of interval
items from original list 尝试用原始列表中
interval
项的相同顺序填充aux
I try to work it out with creating aux
with ArrayList(int initialCapacity)
and initialize it with aux.add(intervals.get(i))
, but failed. 我尝试通过使用
ArrayList(int initialCapacity)
创建aux
并使用aux.add(intervals.get(i))
对其进行初始化来解决aux.add(intervals.get(i))
,但是失败了。 And I still could not figure out why this way doesn't work ? 而且我仍然不知道为什么这种方式行不通?
The full code which can directly used for debug: 可以直接用于调试的完整代码:
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);
}
}
}
Could anyone help me on understanding why must create auxiliary ArrayList aux
with ArrayList<Collection<? extends E> c>
谁能帮助我理解为什么必须使用
ArrayList<Collection<? extends E> c>
创建辅助ArrayList aux
ArrayList<Collection<? extends E> c>
ArrayList<Collection<? extends E> c>
and initialize it with aux.set(i, intervals.get(i));
ArrayList<Collection<? extends E> c>
并使用aux.set(i, intervals.get(i));
对其进行初始化aux.set(i, intervals.get(i));
? ? Or my understanding goes the wrong way ?
还是我的理解走错了路? Thanks
谢谢
Thanks for important hint from @maraca and @Dukeling, after some work, below is my opinion for the issue here: 感谢@maraca和@Dukeling的重要提示,经过一些工作,以下是我对此问题的看法:
Q1 : Why using List<Interval> aux = new ArrayList<Interval>(len);
Q1 :为什么使用
List<Interval> aux = new ArrayList<Interval>(len);
with aux.add(intervals.get(i));
与
aux.add(intervals.get(i));
not work ? 不行 ?
A1 : There are two main issues here, I should admit I fail into some habitual thoughts as previous work with array
implementation of MergeSort
, the impact here are (1) new ArrayList<Interval>(len)
equal to new Interval[len]
or not ? 解答1 :这里有两个主要问题,我应该承认我以前习惯使用
MergeSort
array
实现工作时有些习惯性想法,对这里的影响是(1) new ArrayList<Interval>(len)
等于new Interval[len]
或不是吗 (2) aux[i] = intervals[i]
(just for explain, not use =
in real code) equal to aux.add(intervals.get(i))
? (2)等于
aux.add(intervals.get(i))
aux[i] = intervals[i]
(仅用于解释,不使用=
在实际代码中aux.add(intervals.get(i))
?
For problem (1), the real case here is using new ArrayList<Interval>(len)
will only define the initial limitation of ArrayList
size, but no real items used like space holder to fill into the initialized list, eg If we set len = 4
, the initialized list is actually []
, not [interval obj, interval obj, interval obj, interval obj]
. 对于问题(1),这里的实际情况是使用
new ArrayList<Interval>(len)
仅定义ArrayList
大小的初始限制,但没有像空格符之类的实际项用于填充初始化列表,例如,如果设置len = 4
,初始化的列表实际上是[]
,而不是[interval obj, interval obj, interval obj, interval obj]
。 Assume using new ArrayList<Interval>(len)
with aux.set(i, intervals.get(i))
, IDE will throw out java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
, that's because no real object fill into this list as initialized and set method cannot work on an empty list. 假设使用带有
aux.set(i, intervals.get(i))
new ArrayList<Interval>(len)
,IDE将抛出java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
,这是因为没有真正的对象填充此列表已初始化,并且set方法无法在空列表上使用。 The solution for this issue is create len
numbers of dummy interval
objects to fill in list when initialized, such as List<Interval> aux = new ArrayList<Interval>((Arrays.asList(new Interval(), new Interval(), new Interval(), new Interval())));
针对此问题的解决方案是创建
len
虚设数interval
对象初始化时,比如,以填补在列表中List<Interval> aux = new ArrayList<Interval>((Arrays.asList(new Interval(), new Interval(), new Interval(), new Interval())));
, but since we don't care what initialized first on auxiliary list, just used as place holder and in case of the objects are too many, above code can be replaced with List<Interval> aux = new ArrayList<Interval>(intervals);
,但是由于我们不在乎首先在辅助列表上初始化的对象,仅用作占位符,并且在对象过多的情况下,可以将以上代码替换为
List<Interval> aux = new ArrayList<Interval>(intervals);
which return to our right solution. 回到我们正确的解决方案。
For problem (2), the real case here is using aux.add(intervals.get(i))
not equal to aux[i] = intervals[i]
, at least we should use set()
instead of add()
, because add()
will continually append on aux
, which not MergeSort
suppose to, because MergeSort
require exactly same size auxiliary collection copy to help sorting. 对于问题(2),这里的实际情况是使用
aux.add(intervals.get(i))
不等于aux[i] = intervals[i]
,至少我们应该使用set()
而不是add()
,因为add()
将连续追加到aux
,而这并不是MergeSort
假定的,因为MergeSort
需要大小完全相同的辅助集合副本来帮助排序。 Still use same example to explain what happened when using add()
仍然使用相同的示例来解释使用
add()
时发生的情况
Note after the 3rd merge, the aux
size increase to double size of original list, this will cause indices issue when copy back to original list. 请注意,在第三次合并后,
aux
大小将增加到原始列表的两倍,这将导致在复制回原始列表时出现索引问题。 But if we are using set()
will not cause this trouble. 但是,如果我们使用
set()
不会造成此麻烦。
Q2 : If still want to use add()
what is the proper way ? Q2 :如果仍然想使用
add()
的正确方法是什么?
A2 : As mentioned by @Dukeling, we need to clear()
the aux
before final round copy from original list to auxiliary list, eg like before the 3rd merge happen on above example. A2 :如@Dukeling所述,我们需要在从原始列表到辅助列表的最终回合复制之前
clear()
aux
,例如,如上例中的第三次合并之前。
The working code with add()
and clear()
below: 下面带有
add()
和clear()
的工作代码:
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++));
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.