简体   繁体   English

遍历数组列表的时间复杂度

[英]time complexity for iterating through an array list

I have an array list which I iterate through.我有一个我遍历的数组列表。 In each iteration I call get() to get one element, and if that item passes some condition, it is added to a new array list using add()在每次迭代中,我调用get()来获取一个元素,如果该项目通过某个条件,则使用add()其添加到新的数组列表中

List<Item> items = new ArrayList<Item>();
List<Item> lessItems = new ArrayList<Item>();
for(int index = 0; index < items.size(); index++){
    Item toCheck = items.get(i);
    if(toCheck meets some condition){
        lessItems.add(toCheck);
    }
}

I am not sure what the time complexity is here.我不确定这里的时间复杂度是多少。 I am calling get() on all items so that is O(n).我在所有项目上调用 get(),所以是 O(n)。 Then I am also calling add() on potentially all the items so there's another O(n).然后我还可能在所有项目上调用 add(),因此还有另一个 O(n)。 Not too sure on this one.对这个不太确定。

  1. Your first loop for iterating items list: complexity is O(n)迭代items列表的第一个循环:复杂度为O(n)
  2. Insert each item to end of list lessItems : in normal array it will be O(n) as others said.将每个项目插入到列表lessItems :在普通数组中,正如其他人所说的那样,它将是O(n) But Java implements for ArrayList using amortized array .但是 Java 使用摊销数组实现ArrayList This means when inserting at the end of array, algorithm only costs Amortized O(1) .这意味着在数组末尾插入时,算法仅花费Amortized O(1) Or you can say O(1)或者你可以说O(1)

So complexity of your code is: O(n) * amortized O(1) .所以你的代码的复杂性是: O(n) * amortized O(1) In short is O(n)简而言之就是O(n)

Another reference:另一个参考:

dynamic array 动态数组

Additional note 1:附加说明 1:

If complexity of inserting at the end of array is O(N) , so the total complexity is O(N^2) , not O(2*N) as other answers said.如果在数组末尾插入的复杂度是O(N) ,那么总复杂度是O(N^2) ,而不是其他答案所说的 O(2*N) 。 Because the total complexity for inserting would be: 1 + 2 + 3 + ...+ n = n*(n+1)/2因为插入的总复杂度为: 1 + 2 + 3 + ...+ n = n*(n+1)/2

Addtional Note 2:补充说明 2:

as official document states:正如官方文件所述:

The size, isEmpty, get, set, iterator, and listIterator operations run in constant time. size、isEmpty、get、set、iterator 和 listIterator 操作在恒定时间内运行。 The add operation runs in amortized constant time , that is, adding n elements requires O(n) time. add 操作在分摊常数 time 内运行,即添加 n 个元素需要 O(n) 时间。 All of the other operations run in linear time (roughly speaking).所有其他操作都在线性时间内运行(粗略地说)。 The constant factor is low compared to that for the LinkedList implementation.与 LinkedList 实现相比,常量因子较低。

Additional note 3:附加说明 3:

Here is the logic of grow method that I have taken from official java source code:这是我从官方java源代码中获取的grow方法的逻辑:

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

As the source code has said, when program add element that make size of array larger than current capacity, Array will be grown.正如源代码所说,当程序添加使数组大小大于当前容量的元素时,数组将增长。 new size of grown array will be:增长数组的新大小将是:

int newCapacity = oldCapacity + (oldCapacity >> 1);

This is a trick that make inserting is amortized O(1)这是一个使插入amortized O(1)的技巧

You are doing an iteration, and that's of O(n).你正在做一个迭代,这是 O(n)。

You're also adding items to an ArrayList, which is of O(1) ( Amortized )您还将项目添加到 ArrayList,这是 O(1) (摊销

Getting an index is also O(1).获取索引也是 O(1)。

So your doing O(n) times, operations of O(1), which is going to be of O(n) .所以你做 O(n) 次,O(1) 的操作,这将是O(n)

Big-O and similar notations are asymptotic bounds on time complexity. Big-O 和类似的符号是时间复杂度的渐近界限。 They discard the numeric coefficient and are used to estimate run-time as a function of size of input.它们丢弃数字系数,并用于估计作为输入大小函数的运行时间。

So, 2*n , 3*n ,etc.因此, 2*n3*n等。 are represented as O(n) , and 2*nlog(n) , 3*nlog(n) ,etc.表示为O(n)2*nlog(n)3*nlog(n)等。 are represented as O(nlog(n)) .表示为O(nlog(n))

Since the add() operation inserts only one element in this case, its runtime is approximately, (some small constant)k*1 , giving the total runtime as (some constant)j*(n+some constant(k)) , in other words j*n , or O(n) .由于 add() 操作在这种情况下只插入一个元素,它的运行时间约为, (some small constant)k*1 ,给出总运行时间为(some constant)j*(n+some constant(k)) ,在换句话说j*nO(n)

In this case and all such similar cases, any constant k multiplied by n would be represented as O(n) meaning the runtime varies linearly with size of the input ArrayList.在这种情况下和所有类似的情况下,任何常数k乘以n将表示为O(n)这意味着运行时间随输入 ArrayList 的大小线性变化。

For iterating through the array list, the time complexity will be O(n).对于遍历数组列表,时间复杂度将为 O(n)。 n will be the size of the list. n 将是列表的大小。

for getting the value using get(), it will be O(1), random access is possible in array list using index.为了使用 get() 获取值,它将是 O(1),可以使用索引在数组列表中进行随机访问。

And for adding the values using add(), the value is getting added at the last, so it will be O(1).对于使用 add() 添加值,该值是最后添加的,因此它将是 O(1)。

The time complexity of this operation will be O(n).此操作的时间复杂度为 O(n)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM