Complexity of grow and add
There is one part of a complexity claim we have not looked at yet: whether it is about a single operation or a sequence of them. DynamicArray.add is the example for that, because a single call and a long run of calls tell very different stories about it.
Let’s do the single call first. We have time, space, best case, and worst case now, so let’s apply all of them to add and to the grow that add calls when the array is full.
Here is grow:
private void grow() {
int[] bigger = new int[arr.length * 2];
for (int i = 0; i < size; i++) {
bigger[i] = arr[i];
}
arr = bigger;
}
Let be the number of elements stored in the array.
Time is . Creating bigger takes time, because Java initializes all slots to zero. The loop then runs times, copying one element each pass, and one copy is a constant amount of work. Reassigning arr is one step. Both array creation and copying take time, so the total time is .
Space is . The input space is , because grow starts with the original array arr, which holds elements. The auxiliary space is the new bigger array, which holds slots. Big-Oh suppresses the coefficient, so is as well. Both parts are , so the total is .
Now consider the add method, which calls grow when the array is full:
public void add(int value) {
if (size == arr.length) {
grow();
}
arr[size] = value;
size++;
}
The if at the top of add gives us two cases, so let’s take them separately. Which case we are in depends on whether the array is full, so this is a best-case and worst-case question.
Best case: the array is not full. The if condition is false, so add skips grow, writes one slot, and increments size. That is a fixed number of steps regardless of , so the time is . The auxiliary space is too, because add allocates nothing. The input space is . The only parameter is value, but add is a method on a DynamicArray object, so it starts with the object’s fields too. The input is whatever the method starts with, and that includes arr, which holds elements. So the space complexity is , and all of that is input space. (To be more careful, we should count the input space as : removing elements decreases but does not shrink the backing array.)
Worst case: the array is full. Now the if condition is true and add calls grow. We just worked out that grow costs time and allocates auxiliary space. After grow returns, add writes one slot and increments size, which is a constant amount of work. So the whole call is , which is time, and the auxiliary space is the new array grow allocated, .
By our convention that an unqualified Big-Oh means the worst case, add has a time complexity of and a space complexity of .