Amortized Analysis

Solution

The total cost of a sequence of operations divided by the number of operations in the sequence.

For the rest of this section, consider a DynamicArray data structure, which stores int values in an internal array arr and tracks how many are in use with size. When add finds the internal array full, it calls grow, which allocates a bigger array, copies the size elements into it, and makes it the new arr. Let be the number of elements stored.

Solution

Every add after the first finds the array full. The 2nd add copies element, the 3rd copies , and so on up to the $n$th, which copies :

Dividing of total work by adds gives amortized per add.

Solution

A grow happens when the array holds , , , …, elements, and copies that many:

Dividing of total work by adds gives amortized per add.

Solution

A factor of still gives amortized: any factor greater than makes the number of grow calls logarithmic in , so the total copying is a geometric series, which is . Growing by slots gives amortized, the same as growing by one slot: grow runs every $100$th add, so the number of grow calls is , still linear in , and each copies up to elements, so the total is .

Solution

Average case averages over a distribution of inputs and needs an assumption about which inputs are likely. Amortized averages over a sequence of operations and assumes nothing about probability. The bound on add holds for any sequence of adds, so it is amortized.

Solution

SortedArray.add is amortized. Starting from an empty array of fixed initial capacity, the copying in grow is the same as for DynamicArray: copies over calls. The shifting is the problem. Add values in descending order. Every new value belongs at index , so the $k$th call shifts all elements already stored:

The total is , and dividing by calls gives amortized per call. This matches the worst-case bound for a single call. Amortized analysis does not have to give a better bound: it measures the cost per operation over a worst-case sequence. Doubling spreads the cost of growing over enough adds to give amortized growth cost. But in this descending-order sequence, every add shifts all the elements already stored, so the shifting still costs amortized per add.