为什么AbstractList.removeRange需要二次时间?

时间:2012-08-04 18:18:34

标签: java collections big-o time-complexity

我可以在文档中看到:

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();
        }
    }

对我来说似乎是线性的...但我必须是错的,因为我是这种算法的新手。请帮我理解。

2 个答案:

答案 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;
            }
        }
    }
}