Arraylist时间复杂度:您是否同时根据需要复制和移动元素?

时间:2015-09-15 23:24:53

标签: java arraylist time-complexity add

我试图找出这两种方法之间时间复杂度的差异:

public ArrayList<Integer> populateList(int n){
  ArrayList<Integer> list = new ArrayList<Integer>();
  for(int i=0; i< n; i++)
     list.add(0, i);
     return list;
  }

public ArrayList<Integer> populateList(int n){
  ArrayList<Integer> list = new ArrayList<Integer>();
  for(int i=0; i< n; i++)
    list.add(i);
    return list;
  }   

据我所知,big-o是根据最坏情况定义的,最糟糕的情况是添加到arraylist包括调整大小,从而将所有元素复制到一个新数组中。我认为方法2将是O(n ^ 2),因为对于数组中的每个元素,您可能必须将所有元素复制到更大的数组中。

但我不确定方法1,因为我不确定事情的顺序。似乎复制元素和插入新元素可以组合在一起,这样您就不必首先将旧元素添加到更大的列表中,然后在添加新元素时根据需要移动所有元素。如果是这种情况,似乎方法1是O(n ^ 2)而不是O(n ^ 3)。但这是怎么回事?

2 个答案:

答案 0 :(得分:1)

ArrayList由数组支持。如果你&#34;插入&#34;在数组头部的元素,你必须将所有其他元素向右移动一个以腾出空间。这意味着单次调用:

list.add(0, i);

O(n),因为必须移动每个元素(已添加) 如果您n次执行此操作,则O(n^2)

但是在(支持)数组的末尾添加一个元素:

list.add(i);

只需要在数组的未使用元素中放置一个值,即O(1),除非数组已满,另一个更大的数组需要分配和复制到O(n),但是随着阵列的增长,频率不断下降,特别是O(log n)

如果您执行O(1)的操作,O(n)除了log nn次,O(n log n)次,sex

答案 1 :(得分:0)

方法1是O(n ^ 2)

方法2比O(n ^ 2)好得多:存储数据的内部数组分配有一些自由空间,内部数组增长是指数级的,因此n个元素的迭代很少发生。由于您最后追加,因此没有其他理由在每一步迭代所有元素。