23

Why ArrayList add() and add(int index, E) complexity is amortized constant time?

Why not O(1) for single add() operation, O(n) for single add(int index, E) operation and O(n) for adding n elements (n add operations) using either (any) add method? Supposing we are using add(int index, E) to add to array end rarely?

Isn't one operation complexity of array (and ArrayList) already having n elements:

  1. add() - O(1)?
  2. add(int index, E) - O(n)?

If we make a million insertions, the average of 1 and 2 cannot be O(1), right?

Why Oracle says

The add operation runs in amortized constant time, that is, adding n elements requires O(n) time.

I thought complexity is O(1) for add() and O(n) for add(int index, E).

Does it means that "integral complexity of n operations" (each operation of complexity O(1)) is so to speak n*O(1) = O(n). What am I missing?

Maybe for Oracle "add operation" always means only add()? And add(int, E) is "insertion operation"? Then totally clear!

I have a guess, it has to do with difference between asymptotic analysis and amortized analysis, but I cannot grasp it to the end.

What is amortized analysis of algorithms?

Why the time complexity of an array insertion is O(n) and not O(n+1)?

More appropriate to say Amortized O(1) vs O(n) for insertion into unsorted dynamic array? (not quite clear)

Big O when adding together different routines

Code Complete
  • 3,146
  • 1
  • 15
  • 38
  • Isn't inserting with add(int index, E) 99% of time is not at array end, meaning it also triggers move of at least some rightmost elements, and for big enough array (already having many elements inserted) such moving is always O(n)? Regardless of capacity / resizing issues? Meaning add(int index, E) is (almost) always O(n)? So why amortized O(1)? – Code Complete Jul 20 '17 at 17:12
  • Who said `add(int, E)` wasn't O(n)? – Louis Wasserman Jul 20 '17 at 17:22
  • But what Oracle meant in ArraList docs: "The add operation runs in amortized constant time"??? They mean only add()? And let us guess what they mean? Probably they call add(int, E) as "insert", not add... – Code Complete Jul 20 '17 at 17:28
  • 4
    Yes, that only refers to `add(E)`. – Louis Wasserman Jul 20 '17 at 17:30
  • the source code tells you everything you need to know –  Jul 21 '17 at 17:37

1 Answers1

38

In Oracle terms (which are implied tacitly) and speaking about List

  • "add method" (synonym - "append method") always means boolean add(E)
  • "insert method" always means boolean add(int index, E)

When Oracle writes

The add operation runs in amortized constant time, that is, adding n elements requires O(n) time.

it means:

Complexity of a single boolean add(E) operation is amortized O(1).

It cannot be just O(1) asymptotic (always) because rarely we need to grow array capacity. This single add operation which is in fact a "create new bigger array, copy old array into it, and then add one element to the end" operation is O(n) asymptotic complexity, because copying the array when increasing List capacity is O(n), complexity of growing plus addding is O(n) [calculated as O(n) + O(1) = O(n)]. Without this capacity growing operation, add complexity would have been O(1), element is always added (appended) to the end of array (max index). If we "added" (= inserted) not to array end, we would need to move rightmost elements (with bigger indexes), and complexity for single such operation would have been O(n).

Now, for a single add operation asymptotic complexity is O(1) for add-without-increasing-capacity and O(n) for add-with-increasing-capacity (which happens very rare).

Amortized complexity of a single add operation is O(1). It reflects the fact that rare O(n) grow-and-add operations get "diluted" with much more numerous O(1) add-without-grow ones, so "on the average" single operation is O(1).

"Asymptotic complexity" of n add operations is O(n). But here we speak about complexity of n operations, not complexity of one operation. It is not a strict way to put it like this ("Asymptotic complexity"), but anyway. Amortized complexity of n operations is even less sense.

Finally, boolean add(int index, E) single operation complexity is always O(n). If it triggers grows, it is O(n) + O(n) [grow + insert], but 2*O(n) is same as O(n).

Code Complete
  • 3,146
  • 1
  • 15
  • 38
  • so i understand that in the internal state of the ArrayList class , it contains n synchronized incremented index which holds the index of the last added element , which leads to O(1) time complexity to add a new element in the tail of the array ? – bwass31 Aug 29 '22 at 13:03