Overview:

1. Resizing arrays and amortized analysis.
2. Sets: Disordered & order
3. Binary Search

Strategies for Programming Success

• segment your time, often 5 * 2hr > 10hr.
• start early
• skim provided codes
• work incrementally
• write a method, test and varify, then move on. (write a helper method if needed)

• n = current size of list
• assume size < capacity

What’s the running time of each line in add(i, x)?

 1 2 3 4 5 6 7 8 ++size; // O(1) Object cur = x; // O(1) since it is just assignment for (int j = i, j < size; ++j) { // O(1) since it is just primary ops Object next = contents[j]; // O(1) also assignment contents[j] = cur; // O(1) also assignment cur = next; // O(1) also assignment }

a single iteration is constant and doesn’t depend on size. How many iterations: n - i + 1 overall running time is $$(n - i + 1) O(1) + O(1) = O(n-i+1)$$ This means adding at the end is more efficient than adding in the front.

• peek() –> get(size - 1)
• pop() –> remove(size -1)

Running time of increaseCapapcity()

 1 2 3 4 5 6 7 private class increaseCapacity(){ Object[] bigContents = new Object[capacity + 1]; // O(n+1) for (int i = 0; i < capacity; ++i) { bigContents = contents[i]; // O(1) } }

The for loop: O(n) <– O(1) per iteration + n interations The whole method: $$O(n) = O(n+1) + O(n) + O(1)$$

Running time of buildStack(stk, size)

For loop:

• n interations
• stk.push(i) takes:
• O(1) if no resize
• O(n) if resize (invoke increaseCapacity())

Overall running time: $$n * O(n) = O(n^2)$$ n = number of interations O(n) = time to resize

Although one operation may be expensive, when averaged across operations, overall cost is less expensive.

Amortized Analysis

Idea: Rather than paying worst-case cost for each op, average cost over all sequences of ops.

• e.g. expensive ops like resize are infrequent, so average add time is small.

Banker’s view: Each op has cost (running time)

• have an account $A$ that we can deposit to / withdraw from
• amortized cost of op is
• $ac(op) = cost(op) + bal(A’) - bal(A)$ bal = get balance of account

Amortized cost is average cost per op over sequence of ops.

Example. push op for stack, with capacity doubling Suppose last resize was at size $N$, new capacity $2N$.
Total cost of next resize $C_{2N} = O(2N) = O(N)$

If N ≤ size < 2N, on push op:

• pay $O(1)$ for push without resize
• also put $\displaystyle \frac{1}{N} * C_{2N} = \frac{1}{N} * O(N) = O(1)$ in bank –> amortized cost of push op is $$ac(push) = O(1)$$

If size = 2N, on push op:

• pay push out pocket $O(1)$
• pay resize out account - decrease act by $C_{2N}$ –> amortized cost is \begin{aligned} ac(push) &= cost(push) + cost(resize) + \Delta A\\ O(1) &= O(1) + C_{2N} - C_{2N} \end{aligned}