BITS Pilani
CS F364: Design and Analysis of Algorithms

Further Amortized Analysis

Lecture 21 |2026-06-12

Today’s Agenda: Two Case Studies

We will master the three methods of amortized analysis: 1. Aggregate Method (Global brute-force counting) 2. Accounting Method (Credit/Debit system) 3. Potential Method (Physicist’s energy model)

Applied to two classic problems: * Multipop Stack (Amortized O(1) operations) * Dynamic Tables (Amortized O(1) insertions)

Case Study 1: The Multipop Stack

Standard Stack augmented with a third operation:

  • PUSH(x): push x onto stack — actual cost 1
  • POP(): pop top element — actual cost 1
  • MULTIPOP(k): pop up to k elements: c = \min(k, \text{stack size})

The Worst-Case Trap

A single MULTIPOP(n) operation could cost O(n) if the stack is full. * Does a sequence of n operations cost O(n^2)?

Multipop Stack: Aggregate Method

Key Insight: An element must be PUSHed onto the stack before it can be POPped.

  • Each PUSH adds exactly one element.
  • Each POP (including those inside MULTIPOP) removes exactly one element.
  • Therefore: \text{Total POPs} \le \text{Total PUSHs} \le n

Total Cost of n Operations: \text{Cost}_{\text{total}} = \text{Total PUSH cost} + \text{Total POP/MULTIPOP cost} \text{Cost}_{\text{total}} \le n + n = 2n

Amortized Cost per operation: \le 2n / n = O(1). ✓

Multipop Stack: Accounting Method

We assign artificial amortized costs (charges) to operations:

  • PUSH(x): Charge 2 credits
    • 1 credit pays for the PUSH itself.
    • 1 credit is stored on the element in the stack.
  • POP() & MULTIPOP(k): Charge 0 credits
    • The actual cost of popping an element is paid using the 1 credit stored on that element.

Credit Invariant: \text{Total Amortized Cost} - \text{Total Actual Cost} = \text{Credit Balance} = \text{Stack Size} \ge 0 Since balance is always non-negative, amortized cost bounds actual cost. Amortized cost = O(1) per operation. ✓

Multipop Stack: Potential Method

Define potential function: \Phi(D_i) = \text{size of stack}.

  • Verification: \Phi(D_0) = 0 (empty stack) and \Phi(D_i) \ge 0 for all i.

Amortized Cost Derivations (\hat{c}_i = c_i + \Phi(D_i) - \Phi(D_{i-1})):

  1. PUSH: \hat{c}_i = 1 + (\text{size} + 1 - \text{size}) = 2
  1. POP: \hat{c}_i = 1 + (\text{size} - 1 - \text{size}) = 0
  1. MULTIPOP(k): (pops k' = \min(k, s) elements) \hat{c}_i = k' + (\text{size} - k' - \text{size}) = 0

Amortized cost is O(1) per operation. ✓

Concept Check: Multipop Stack

Question for the Class

“What if we define our potential function as \Phi(D_i) = 2 \cdot \text{stack size}? Will the analysis still work? What will be the new amortized costs?”

Answer: Yes, it still works. * PUSH: \hat{c}_i = 1 + 2(1) = 3 * POP: \hat{c}_i = 1 + 2(-1) = -1 \le 0 * MULTIPOP(k): \hat{c}_i = k' + 2(-k') = -k' \le 0 Amortized bounds are still O(1) per operation!

Case Study 2: Dynamic Tables

Problem: We need an array that dynamically resizes to accommodate insertions. * Start with size 1. * When table is full and we insert, we double its size and copy all elements to the new memory block.

Cost Model

  • Insertion without doubling: actual cost = 1 (write).
  • Insertion with doubling from size m: actual cost = 1 + m (write + m copies).

Dynamic Tables: Walkthrough

Let’s trace the actual cost of the first 16 insertions:

i size before copy cost insert cost actual cost cumulative cost
1 1 0 1 1 1
2 1 (full) 1 1 2 3
3 2 0 1 1 4
4 2 (full) 2 1 3 7
5–7 4 0 1 each 1 each 10
8 4 (full) 4 1 5 15
9–15 8 0 1 each 1 each 22
16 8 (full) 8 1 9 31

Notice that for n=16, total actual cost is 31 < 2n.

Dynamic Tables: Aggregate Method

Generalizing the trace: Doubling occurs only when i - 1 is a power of 2.

Total Cost of n Insertions: T(n) = \sum_{i=1}^{n} c_i = n + \sum_{k=0}^{\lfloor \log_2(n-1) \rfloor} 2^k T(n) < n + 2 \cdot 2^{\lfloor \log_2(n-1) \rfloor} < n + 2n = 3n

Amortized Cost per Insertion: \hat{c} = \frac{T(n)}{n} < \frac{3n}{n} = 3 = O(1)

Dynamic Tables: Accounting Method

Accounting Scheme: Charge 3 credits per insertion. * 1 credit pays for the insertion itself. * 1 credit is stored on the element to pay for its future copy. * 1 credit is stored to pay for copying an older element.

Why does this cover all copying? Between size m (just doubled) and 2m (full): * We perform m insertions. * The last m/2 insertions generate m/2 \times 2 = m credits. * When table becomes full, we have exactly m credits in the pool. * This pays for copying all m elements during the next doubling.

Dynamic Tables: Potential Method

Define potential function: \Phi(D_i) = 2 \cdot \text{num}_i - \text{size}_i

  • Properties: \Phi(D_0) = 0. Since table is always at least half full (after first insertion), \Phi(D_i) \ge 0.

Amortized Cost (\hat{c}_i = c_i + \Delta\Phi):

  1. Case 1: No Expansion (\text{num}_i = \text{num}_{i-1} + 1, \text{size}_i = \text{size}_{i-1}) \hat{c}_i = 1 + (2 - 0) = 3
  1. Case 2: Expansion (\text{size}_{i-1} = m, \text{size}_i = 2m, \text{num}_{i-1} = m) \hat{c}_i = \underbrace{(1 + m)}_{\text{actual cost}} + \underbrace{[2(m + 1) - 2m]}_{\text{new potential}} - \underbrace{[2m - m]}_{\text{old potential}} \hat{c}_i = 1 + m + 2 - m = 3

Amortized cost is 3 = O(1) per insertion. ✓

Concept Check: Dynamic Tables

Question for the Class

“Why is charging 2 credits per insertion insufficient? Show at which step the credit invariant fails.”

Answer: Right before doubling from size m to 2m, we have done m/2 new insertions. * If we charged 2 credits (1 for insert, 1 saved), we would only have m/2 credits in the pool. * But copying m elements requires m credits. The invariant fails and the pool goes negative.

Summary: Amortized vs Worst-Case

Data Structure Operation Worst-Case Cost Amortized Cost
Binary Counter INCREMENT O(k) O(1)
Multipop Stack PUSH / POP / MULTIPOP O(n) O(1)
Dynamic Table INSERT O(n) O(1)

Important

Takeaway: Amortized analysis gives a realistic guarantee of performance over a sequence of operations, proving that rare expensive operations do not ruin global efficiency.