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

Java Arraylist时间复杂度:是否根据需要同时复制和移动元素?,java,arraylist,time-complexity,add,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> popu

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

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;
  }   
public ArrayList populateList(int n){
ArrayList=新建ArrayList();
对于(int i=0;i
我知道big-o是根据最坏情况定义的,而添加到arraylist的最坏情况是调整大小,从而将所有元素复制到一个新数组中。我认为方法2应该是O(n^2),因为对于数组中的每个元素,都有可能需要将所有元素复制到一个更大的数组中

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

方法1是O(n^2)


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

ArrayList
由数组支持。如果在数组的头部“插入”一个元素,则必须将所有其他元素向右移动一次以腾出空间。这意味着一次呼叫:

list.add(0, i);
O(n)
,因为必须移动每个元素(已添加)。
如果你这样做
n次
,它是
O(n^2)

但在(备份)数组的末尾添加一个元素:

只需要在数组中未使用的元素中放入一个值,即
O(1)
,除非数组已满并且需要分配和复制另一个更大的数组,即
O(n)
,但这种情况只会随着数组的增长而发生,尤其是
O(log n)


如果你做的操作是
O(1)
,除了
O(n)
log n
次,
n
次,那就是
O(n log n)
,我对最坏情况下的工作原理有点困惑。很少,但有时,方法2会是O(n^2),不是吗?这些不经常发生的事件是否构成了整个算法的大o?方法2是简单的O(n)吗?是的,方法2是O(n)——这里有一个很好的解释:这非常有用。非常感谢。
list.add(i);