我可以在文档中看到:
java.util.AbstractList#removeRange
它需要二次时间:
此实现获取一个位于fromIndex之前的列表迭代器, 并反复调用ListIterator.next,然后调用ListIterator.remove 直到整个范围被删除。注意:如果是ListIterator.remove 需要线性时间,这种实现需要二次时间。
但为什么?代码:
protected void removeRange(int fromIndex, int toIndex) {
ListIterator<E> it = listIterator(fromIndex);
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
it.next();
it.remove();
}
}
对我来说似乎是线性的...但我必须是错的,因为我是这种算法的新手。请帮我理解。
答案 0 :(得分:4)
重要的部分是“注意:如果ListIterator.remove需要线性时间,则此实现需要二次时间。” for循环需要线性时间,你是对的。但是,如果您在每次迭代时执行线性时间步长,则会得到n * n = n^2
。
答案 1 :(得分:3)
原因在于:
it.remove();
可以是列表上的O(n)操作,您可以在O(n)循环中调用它。
换句话说,如果是这样的话,你的真实循环会是这样的(我做了但是你明白了):
protected void removeRange(int fromIndex, int toIndex) {
ListIterator<E> it = listIterator(fromIndex);
for (int i = 0, n = toIndex - fromIndex; i < n; i++) {
E item = it.next();
//it.remove();
for (int j = ; j < n; j++) {
if (list.get(j).equals(e)) {
list.remove(e);
break;
}
}
}
}