Aside — Amortized Time Complexity
Warning
This explanation of amortized time complexity analysis is brief and high-level as it is outside the scope of this course. It is only included here for those interested as some may find that the additional context helps with their understanding.
There’s actually a bit of a gotcha in the push example for an
ArrayStack
1 @Override
2 public boolean push(T element) {
3 if (size() == stack.length) {
4 stack = expandCapacity(stack);
5 }
6 stack[top] = element;
7 top++;
8 return true;
9 }
10
11 /**
12 * Returns a new array with double the size of the stack array container and copy the contents from the old array to
13 * the new array.
14 */
15 @SuppressWarnings("unchecked")
16 private T[] expandCapacity(T[] oldStack) {
17 T[] newStack = (T[]) new Object[oldStack.length * 2];
18 for (int i = 0; i < oldStack.length; i++) {
19 newStack[i] = oldStack[i];
20 }
21 return newStack;
22 }
Since
expandCapacityis an \(O(n)\) methodAnd since
pushcallsexpandCapacity,pushwill at least be \(O(n)\)However, how often is
expandCapacityactually called?
Amortization
The trick is to realize that the work can be amortized, or, spread out over multiple calls of
push
Consider an empty
ArrayStackwith a capacity of \(n\)A total of \(n\) constant time
pushoperations can occur before the capacity it hit\(n \times O(1)\) operations
The \((n+1)^{th}\)
pushwill require a call toexpandCapacity, which is a linear time operation\(1 \times O(n)\) operation
In other words, the \(O(n)\) operation gets called once every \(n\) constant time calls of
pushThis \(O(n)\) work can be amortized/spread out over the \(n\) constant time calls
Consider all this as a roughly calculated expression to shows how much work is being done, on average, over the \(n + 1\)
pushcalls\(=\frac{n \times O(1) + 1 \times O(n)}{n + 1}\)
\(= \frac{n \times O(1)}{n + 1} + \frac{1 \times O(n)}{n + 1}\)
\(\approx O(1) + O(1)\)
\(\approx 2 \times O(1)\)
\(\approx O(1)\)
The below figures show a visualization of how one can think of the work being amortized
Depiction of the amount of work taking place for each of the \(n + 1\) calls to push.
A depiction of all the work required for the \(n + 1\) calls to push amortized over the previous \(n\)
calls to push.