Amortized Analysis: The Aggregate Method

A dynamic array doubles its capacity when full. This operation seems to cost linear time. Yet in practice, appending a million elements runs in time proportional to a million. It does not run in time proportional to a million squared. Something in the analysis of "worst case per operation" is too pessimistic. Understanding exactly why is the point of amortized analysis. This article introduces the aggregate method. It is the simplest and most direct technique for proving that a sequence of operations is cheap on average. This holds even when individual operations are occasionally expensive. This matters because real systems are built from data structures that experience exactly this pattern. They are usually cheap, occasionally expensive, and the expensive operations are rare. They are rare enough that they wash out. Dynamic arrays in Python, Java, and C++ standard libraries rely on this pattern. So does the union-find structure inside compilers and network algorithms. So do splay trees in kernel schedulers, and incremental hashing schemes in databases. All of these rely on amortized guarantees rather than uniform worst-case bounds. Without amortized analysis, engineers would either overestimate costs. This would lead to unnecessarily conservative designs. Or they would have no rigorous language at all. They would lack a way to describe "usually fast, rarely slow, always fine in bulk." The big picture is a shift in what quantity we bound. Instead of asking "what is the worst cost of any single operation?", we ask something different. We ask "what is the worst cost of any sequence of nn operations, divided by nn?" The aggregate method answers this directly. It computes (or bounds) the total cost T(n)T(n) of the worst possible sequence. This sequence consists of nn operations on an initially empty structure. It then defines the amortized cost per operation as T(n)/nT(n)/n. This is a statement about sequences, not about probability distributions over inputs. It holds even under adversarial operation orderings. This distinguishes it sharply from Best, Average, and Worst Case Analysis applied to a single operation in isolation. This article builds the aggregate method from first principles. It covers what problem it solves. It shows how to execute the technique step by step on a genuine example. That example is the dynamic array, and separately a binary counter. It shows how to prove the resulting bound is tight and correct. It explains where the method breaks down. Finally, it shows how the method sets up the accounting and potential methods. These generalize it to structures where costs are less uniform.

Key takeaways
  • Amortized analysis bounds the average cost per operation over the worst possible sequence of nn operations, not the worst single operation.
  • The aggregate method computes total cost T(n)T(n) for any sequence of nn operations directly, then sets amortized cost =T(n)/n= T(n)/n.
  • It gives one shared bound for all operation types in the sequence, unlike accounting or potential methods which can assign different amortized costs to different operations.
  • The classic proof: dynamic array doubling costs O(n)O(n) total for nn pushes, so O(1)O(1) amortized per push, because doubling copies form a geometric series summing to O(n)O(n).
  • Correctness rests on a genuine algebraic bound over all sequences — not an average-case probabilistic argument, and not reliant on any particular input distribution.
  • The method is limited to structures where all operations share one amortized cost; when costs must be split per-operation-type, the accounting or potential method (covered next) is required.
The core insight

Amortized cost is not the cost of a typical operation — it is the total worst-case cost of any full sequence of operations, divided evenly across that sequence.

The idea

Amortized analysis answers a question that per-operation worst-case analysis cannot: how expensive is a data structure operation when performed repeatedly, accounting for the fact that expensive operations restore conditions that make many subsequent operations cheap? A single worst-case bound applied to every operation in a sequence of nn operations, then multiplied by nn, is always a valid upper bound on total cost — but it can be wildly loose if expensive operations cannot actually happen often. Amortized analysis produces a tighter, still fully rigorous, bound on the total cost of any sequence, expressed as an amortized cost per operation. The aggregate method is the most direct of the three standard techniques for amortized analysis (the others being the accounting method and the potential method, which generalize this idea to assign different costs to different operation types). Given a sequence of nn operations op1,op2,…,opnop_1, op_2, \ldots, op_n applied to a data structure starting from a fixed initial state (usually empty), let T(n)T(n) denote the true worst-case total cost of any such sequence of length nn. The amortized cost per operation is then defined as

c^=T(n)n.\hat{c} = \frac{T(n)}{n}.

Crucially, this single amortized cost c^\hat c is applied uniformly to every operation in the sequence, regardless of that operation's individual actual cost. The guarantee delivered is: for any sequence of nn operations, the total actual cost is at most n⋅c^n \cdot \hat c. This is a worst-case guarantee over sequences — no assumption of randomness, no average over an input distribution — which is exactly why amortized bounds remain valid even under adversarial usage patterns, a property essential in systems where an adversary (or unlucky user traffic pattern) could otherwise engineer a sequence to repeatedly trigger the worst case. It is important to be precise about what the aggregate method does not claim. It does not claim that every operation costs c^\hat c; some cost far less, some (rarely) cost far more. It does not use probability at all, distinguishing it from average-case analysis via Best, Average, and Worst Case Analysis, which typically assumes a distribution over inputs and computes an expectation. Amortized analysis instead exploits structural facts: that an expensive operation leaves the structure in a state where cheap operations must follow, so expensive operations cannot cluster arbitrarily. The aggregate method proves this by computing T(n)T(n) directly — usually via a summation, a potential telescoping argument, or a clever accounting of "credits" spent — rather than by reasoning operation-by-operation.

How it works

The aggregate method proceeds in three explicit steps, applied to a fixed sequence length nn of operations on an initially empty (or fixed-start) structure.

Step 1 — Identify the true worst-case total cost T(n)T(n). Do not bound each operation separately and sum the bounds; that gives a valid but often loose bound. Instead, analyze the entire sequence together, exploiting the fact that expensive operations (like a resize) change the state in a way that constrains how soon the next expensive operation can occur.

Step 2 — Compute or bound T(n)T(n) using a direct sum, often a geometric or arithmetic series. This is the technical heart of the method. For structures whose expensive operation triggers periodically (every kk-th operation, or whenever a counter overflows), T(n)T(n) decomposes into a sum over "cheap" operations plus a sum over "expensive" operations, and the expensive sum telescopes or collapses via a geometric series identity.

Step 3 — Divide by nn to get the amortized cost, and state the theorem precisely. The final claim is always of the form: "any sequence of nn operations on this structure costs at most O(f(n))O(f(n)) in total, hence O(f(n)/n)O(f(n)/n) amortized per operation." State both forms — the aggregate bound and the per-operation bound — since the aggregate bound is what you actually proved, and the per-operation bound is the more usable design fact. Below is the technique made concrete on the two canonical examples: the dynamic array (`push_back` with doubling) and the binary counter (incrementing). ``` // DYNAMIC ARRAY WITH DOUBLING // State: array A with capacity cap, current size n // Operation: PUSH(x) appends x to the array procedure PUSH(x): if n == cap: allocate new array A' of capacity 2 cap // cost: cap (copy all elements) copy all n elements from A into A' A <- A' cap <- 2 cap A[n] <- x n <- n + 1 // cost of this call: 1 (for the assignment) plus cap if a resize occurred // AGGREGATE ANALYSIS over a sequence of n PUSH operations starting from empty, cap = 1: // // Resizes occur at pushes number 1, 2, 4, 8, 16, ..., i.e. when n reaches a power of two. // At the resize triggered when the array holds 2^i elements, the copy cost is 2^i. // // T(n) = (cost of all n unit assignments) + (cost of all resize copies) // = n + (1 + 2 + 4 + 8 + ... + 2^(floor(log2 n))) // = n + (2^(floor(log2 n) + 1) - 1) // <= n + (2n - 1) [geometric series bound: 2^(floor(log2 n)+1) <= 2n] // = 3n - 1 // // Hence T(n) = O(n), and amortized cost per PUSH = T(n) / n = O(1). ``` ``` // BINARY COUNTER INCREMENT // State: array of bits A[0..k-1], representing a k-bit binary counter, initially all 0 // Operation: INCREMENT flips bits starting from the lowest-order bit procedure INCREMENT(A): i <- 0 while i < length(A) and A[i] == 1: A[i] <- 0 // cost: 1 bit flip (a "reset") i <- i + 1 if i < length(A): A[i] <- 1 // cost: 1 bit flip (a "set") // AGGREGATE ANALYSIS over a sequence of n INCREMENT operations starting from A = 0: // // Cost of one INCREMENT = number of bits flipped = (number of trailing 1s reset) + 1. // Total cost T(n) = sum over all n increments of (bits flipped). // // Key structural fact: bit A[j] flips from 0 to 1 (a "set") exactly once every 2^j increments, // and every flip of A[j] to 1 is later matched by at most one flip back to 0 before it can flip // to 1 again. So over n increments, bit A[j] flips at most floor(n / 2^j) + 1 times total. // // T(n) = sum_{j=0}^{floor(log2 n)} ( floor(n / 2^j) + 1 ) // <= sum_{j=0}^{floor(log2 n)} ( n / 2^j + 1 ) // <= n * sum_{j=0}^{inf} (1/2^j) + O(log n) // = 2n + O(log n) // = O(n) // // Hence amortized cost per INCREMENT = T(n) / n = O(1). ``` The pattern in both examples is identical: identify which "bit" of work each operation touches (an array slot copied during resize, a bit flipped during increment), bound how many times in total, across the whole sequence, that unit of work can occur, sum those bounds (usually a geometric series that telescopes to O(n)O(n)), and divide by nn.

Figure
Dynamic array doubling: cost per push (bars) versus cumulative total cost (line), showing why the amortized cost per operation stays O(1)
PUSH costs over 16 operations (capacity doubles at 1,2,4,8,16) cost operation index (1..16) per-op cost (bars) cumulative T(k) — roughly linear 1 16

Complexity & correctness

Dynamic array claim. For any sequence of nn `PUSH` operations on an initially empty dynamic array starting at capacity 11 and doubling on overflow, the total cost is T(n)=O(n)T(n) = O(n), hence the amortized cost per `PUSH` is O(1)O(1). Proof. Split the total cost into two parts: (a) the cost of the constant-time array-slot writes, one per push, contributing exactly nn; and (b) the cost of copying during resizes. A resize copying mm elements occurs only when the array is full at size mm and mm is a power of two (with the convention that the structure starts at capacity 11), so the sizes at which resizes occur are 1,2,4,8,…1, 2, 4, 8, \ldots up to at most nn. The total copy cost is thus at most

∑i=0⌊log⁡2n⌋2i=2⌊log⁡2n⌋+1−1<2n.\sum_{i=0}^{\lfloor \log_2 n\rfloor} 2^i = 2^{\lfloor \log_2 n \rfloor + 1} - 1 < 2n.

This is a finite geometric series, and the standard identity ∑i=0k2i=2k+1−1\sum_{i=0}^{k} 2^i = 2^{k+1}-1 gives the bound directly, with 2⌊log⁡2n⌋≤n2^{\lfloor \log_2 n\rfloor} \le n ensuring the sum is under 2n2n. Adding the nn unit-cost writes,

T(n)≤n+2n=3n,T(n) \le n + 2n = 3n,

so T(n)=O(n)T(n) = O(n), and the amortized cost per operation is T(n)/n=O(1)T(n)/n = O(1). ■\blacksquare This argument is exact and does not rely on any assumption about which elements are pushed or in what order operations other than `PUSH` occur — it is a genuine worst-case bound over all sequences of nn pushes, because resizes are forced to happen at specific, predictable sizes regardless of the data being pushed.

Binary counter claim. For any sequence of nn `INCREMENT` operations starting from an all-zero kk-bit counter, the total number of bit flips is O(n)O(n), hence O(1)O(1) amortized per increment (independent of kk, so long as nn does not overflow the counter). Proof. Bit A[j]A[j] can only be set to 11 (flip 0→10 \to 1) when the low-order counter value is a multiple of 2j2^j, which happens at most ⌊n/2j⌋+1\lfloor n/2^j \rfloor + 1 times over nn increments; each such set is followed by at most one reset (1→01 \to 0) before the next set. So the total number of flips of bit jj across the sequence is at most 2(⌊n/2j⌋+1)2(\lfloor n/2^j\rfloor + 1). Summing over all bits j=0,…,⌊log⁡2n⌋j = 0, \ldots, \lfloor \log_2 n \rfloor (bits beyond this never flip for a counter incremented only nn times),

T(n)≤2∑j=0⌊log⁡2n⌋(n2j+1)≤2n∑j=0∞12j+O(log⁡n)=4n+O(log⁡n)=O(n).T(n) \le 2\sum_{j=0}^{\lfloor \log_2 n \rfloor} \left(\frac{n}{2^j} + 1\right) \le 2n \sum_{j=0}^{\infty} \frac{1}{2^j} + O(\log n) = 4n + O(\log n) = O(n).

Again the geometric series ∑1/2j=2\sum 1/2^j = 2 is the crux: it converges, so the total flip count stays linear in nn rather than growing with kk or with nlog⁡nn \log n (which is what naive per-operation worst-case analysis, O(log⁡n)O(\log n) flips per increment times nn increments, would suggest). ■\blacksquare

Honesty about what is and is not proven. The aggregate method proves a bound on the sum of costs over a sequence; it says nothing about the cost of an individual operation in isolation, and in particular it never claims that a single "expensive" operation is somehow secretly cheap — one increment really can flip Θ(log⁡n)\Theta(\log n) bits, one push really can trigger an Ω(n)\Omega(n)-time copy. What amortized analysis guarantees is that such expensive operations are rare enough, and correlated tightly enough with recent cheap operations, that the running total stays linear. This is a genuinely different (and often more useful) claim than either worst-case-per-operation analysis or average-case analysis over random inputs, since it holds under adversarial sequencing — an adversary choosing exactly when to push or increment cannot force T(n)T(n) above O(n)O(n), because the structure itself (via doubling capacities, via binary carrying) prevents expensive events from clustering.

A key limitation of the aggregate method is that it produces one amortized cost shared by every operation type in the sequence. If a structure supports several distinct operations with genuinely different amortized costs — for instance a mixture of cheap lookups and occasionally expensive rebalancing insertions where you want separate bounds for each operation type — the aggregate method's single shared c^=T(n)/n\hat c = T(n)/n can be too coarse, or simply awkward to state per operation type. That refinement is exactly the motivation for the accounting method (assigning differing "amortized charges" to different operation types, banking credit) and the potential method (defining a potential function on the structure's state), both of which recover per-operation-type amortized costs while remaining consistent with the aggregate bound.

Worked example

Trace T(n)T(n) explicitly for a dynamic array over n=10n = 10 pushes, starting empty with capacity 11, doubling whenever full.

push #array size beforefull?resize triggered (new cap)copy costwrite costtotal op cost
10cap=0→ must allocatealloc cap=1011
21yes (cap=1)cap=2112
32yes (cap=2)cap=4213
43no—011
54yes (cap=4)cap=8415
65no—011
76no—011
87no—011
98yes (cap=8)cap=16819
109no—011

Summing the "total op cost" column:

T(10)=1+2+3+1+5+1+1+1+9+1=25.T(10) = 1+2+3+1+5+1+1+1+9+1 = 25.

Compare this to the naive (and correct, but loose) worst-case-per-operation bound: the worst single push in this sequence costs 99, so multiplying that worst case by 1010 operations gives an upper bound of 9090 — more than three times the true total of 2525. The aggregate method's actual computation, T(n)≤3nT(n) \le 3n, predicts T(10)≤30T(10) \le 30, which is a tight and honest bound (the true value 2525 sits comfortably under it), while the naive per-operation bound of 9090 dramatically overstates the true cost because it assumes every operation could be as expensive as the single worst one, which the doubling structure makes impossible. The amortized cost per push in this trace is 25/10=2.525/10 = 2.5, consistent with the O(1)O(1) claim (bounded above by 33) and nowhere near the O(n)O(n) that per-operation worst-case analysis alone would suggest if applied naively across a growing sequence. A second trace, for the binary counter, makes the same point with a different mechanism. Starting from `0000` and performing n=8n=8 increments:

increment #counter beforebits flippedflip count
100000000→00011
200010001→00102
300100010→00111
400110011→01003
501000100→01011
601010101→01102
701100110→01111
801110111→10004

Sum of flip counts: 1+2+1+3+1+2+1+4=151+2+1+3+1+2+1+4 = 15. The naive bound (each increment costs up to k=4k = 4 bit flips, times n=8n=8 increments) gives 3232; the aggregate bound T(n)≤4n=32T(n) \le 4n = 32 matches this loose bound closely here because nn is small relative to 2k2^k, but as nn grows toward 2k2^k and beyond, the true total continues to track close to 2n2n–4n4n rather than scaling with kk, exactly as the geometric-series argument predicts — the amortized cost per increment converges to a small constant, not to log⁡n\log n.

Figure
Binary counter bit-flip pattern over 8 increments — low bits flip every step, high bits flip rarely, and the sum stays linear
Bit flips per increment (bit 0 = rightmost) bit 3 bit 2 bit 1 bit 0 123 456 78

Common pitfalls & traps

PitfallWhy it happensFix
Bounding each operation by its own worst case and multiplying by nnTempting shortcut, but ignores that expensive operations restore state that guarantees cheap follow-upsAnalyze the whole sequence's total cost directly, exploiting when expensive events can recur
Forgetting to check that the structure starts from a fixed known stateAggregate bounds are proven for sequences starting empty/reset; a mid-sequence adversarial starting state can break the argumentAlways state and use the initial condition (e.g., empty array, all-zero counter) explicitly in the proof
Treating amortized cost as a probabilistic/average-case guaranteeConfusing "amortized" with "expected" or "average case" — they use entirely different reasoningRemember: amortized bounds hold for every sequence, deterministically, with no distributional assumption
Applying a single global sequence bound to a mixed workload with structurally different operation types and expecting per-type costsAggregate method gives one c^\hat c for the whole sequence, not separate costs per operation kindUse the accounting or potential method when operations have genuinely different amortized costs
Sloppy geometric series bound (off-by-one in the exponent or forgetting the −1-1/+1+1 term)Series like ∑2i\sum 2^i or ∑n/2j\sum n/2^j are easy to mis-index, inflating or deflating T(n)T(n)Write out small cases (n=1,2,3,4n=1,2,3,4) and check the closed form matches before trusting the asymptotic bound
Assuming amortized O(1)O(1) means every call is fast in real timeA single push can still legitimately take Θ(n)\Theta(n) time; only the sequence total is guaranteed cheapState clearly that amortized bounds say nothing about worst-case latency of any one call — relevant for real-time systems

Pioneers & history

The vocabulary and formal apparatus of amortized analysis — the aggregate, accounting (banker's), and potential (physicist's) methods — were crystallized in the early 1980s in the context of analyzing self-adjusting data structures, most famously splay trees and the union-find structure with path compression.

Origins · 1 minRobert Endre Tarjan and how this was discovered
RE
Robert Endre Tarjan
born 1948 · Developed and popularized amortized analysis, notably the potential-function method, while analyzing self-adjusting data structures such as splay trees and union-find with path compression and union by rank.

History
1970
s — union-find with path compression and union by rank analyzed, yielding early amortized-style bounds (inverse-Ackermann growth).
1985
— Sleator and Tarjan introduce splay trees, formalizing the potential-function (physicist's) method of amortized analysis.
1985
— Tarjan's survey "Amortized Computational Complexity" names and unifies the aggregate, accounting, and potential methods.
1990
s — amortized analysis becomes a standard tool in textbook treatments of dynamic arrays, hash table resizing, and disjoint-set structures.
2000
s–present — amortized reasoning extended to concurrent and persistent data structures, and to analyzing incremental/streaming algorithms.

The aggregate method itself predates its formal naming — the doubling-array argument and the binary-counter argument were folklore results used implicitly wherever incremental structures were analyzed — but Tarjan's synthesis gave the field a shared vocabulary and proof template, distinguishing amortized reasoning cleanly from the probabilistic reasoning used in Best, Average, and Worst Case Analysis and connecting it to inductive proof techniques familiar from The Substitution Method.

Where this matters

Dynamic arrays with geometric growth (Python's `list`, Java's `ArrayList`, C++'s `std::vector`) are the textbook application: `append`/`push_back` is documented and relied upon as amortized O(1)O(1), which is precisely the aggregate-method result derived above, and every performance-sensitive system that builds up large collections incrementally depends on this guarantee holding. Hash tables that resize (grow their bucket array) when a load-factor threshold is crossed use the identical doubling argument to guarantee amortized O(1)O(1) insertion, which underlies the performance model of virtually every hash-based associative container in production language runtimes. Union-find (disjoint-set) structures with path compression and union by rank, used inside Kruskal's minimum spanning tree algorithm, in compiler alias analysis, and in dynamic connectivity queries for network monitoring, rely on amortized analysis (via a more refined argument than pure aggregate counting) to justify their near-linear total running time across a sequence of unions and finds. Splay trees, used in some caching layers and in certain kernel/scheduler data structures, guarantee amortized O(log⁡n)O(\log n) per operation even though any single access can take O(n)O(n) time in the worst case — the structure's self-adjusting behavior after each access is exactly what the amortized argument accounts for. Incremental algorithms in streaming and online systems — incrementally maintained checksums, incremental topological sort updates, buffer-flushing policies in write-heavy storage engines — are routinely justified with the same style of "total cost over the whole run is linear" argument that the aggregate method formalizes, making it a foundational tool anywhere a system processes a long stream of small updates punctuated by occasional bulk maintenance work.

Ask the tutor: How does the accounting method's "credit invariant" formally guarantee the same total bound the aggregate method proves directly?

Is amortized analysis the same as average-case analysis?

No. Average-case analysis assumes a probability distribution over inputs and computes an expected cost, so it can be misleading if real inputs don't match that distribution. Amortized analysis makes no probabilistic assumption at all: it proves a bound on the total cost of any sequence of operations, including sequences chosen adversarially to maximize cost. The aggregate method's bound T(n)/nT(n)/n holds for every possible sequence of length nn, not just typical or randomly sampled ones. This is why amortized guarantees are trusted in adversarial or security-sensitive contexts — an attacker crafting inputs to trigger worst-case behavior repeatedly still cannot exceed the amortized bound in total, only redistribute where the cost falls within the sequence.

Does an amortized O(1) operation mean it always runs in constant time?

No — this is the single most common misunderstanding. Amortized O(1)O(1) means the total cost of any nn operations is O(n)O(n), so the average cost per operation is O(1)O(1), but any individual operation in that sequence can still cost far more. A dynamic array's push that triggers a resize genuinely takes Θ(n)\Theta(n) time for that one call. Systems with hard real-time latency requirements per call cannot rely on amortized bounds alone; they need true worst-case-per-call guarantees, which sometimes require different structures (e.g., arrays that resize incrementally across several calls instead of all at once).

How does the aggregate method differ from the accounting method?

The aggregate method computes one shared amortized cost c^=T(n)/n\hat c = T(n)/n that applies uniformly to every operation in the sequence, derived by directly summing or bounding the total cost T(n)T(n). The accounting method instead assigns a (possibly different) amortized charge to each operation type, allowing cheap operations to "overpay" and bank credit that expensive operations later "withdraw," while maintaining the invariant that banked credit never goes negative. The accounting method is more flexible when different operations genuinely deserve different amortized costs, but it requires inventing and verifying a credit-invariant, whereas the aggregate method requires only a direct summation. Both methods, when applicable to the same structure, must agree in their total-cost conclusion.

Why does the geometric series matter so much in these proofs?

Both canonical examples — dynamic array doubling and binary counter incrementing — reduce to summing a geometric-like series: 1+2+4+⋯+2k1+2+4+\cdots+2^k for the array, and ∑n/2j\sum n/2^j for the counter. A geometric series with ratio less than 1 (as in ∑1/2j\sum 1/2^j) converges to a constant, and a growing geometric series ∑2i\sum 2^i up to 2k2^k sums to roughly twice its largest term, 2k+12^{k+1}. This "doubling collapses to linear" phenomenon is precisely why cumulative rare-but-expensive events do not blow up the total cost: each expensive event is roughly twice as costly as the previous one, but occurs roughly half as often, so the products stay bounded and the series telescopes.

Can the aggregate method give a wrong or invalid bound if applied carelessly?

Yes, in two common ways. First, if the initial state of the structure is not fixed (e.g., the array does not start empty, or the counter does not start at zero), the geometric-series argument can fail because resize/carry events may not occur at the predictable sizes the proof relies on. Second, sloppy indexing in the summation (off-by-one errors in exponents, or forgetting that only O(log⁡n)O(\log n) terms exist in the series) can silently produce an incorrect closed form. Always sanity-check the derived bound against a small hand-traced example, as done in the worked-example section, before trusting the asymptotic claim.

Does the aggregate method apply to every data structure with occasional expensive operations?

No. It applies cleanly only when a single amortized cost meaningfully describes the whole operation sequence — typically when there is one dominant operation type, or when all operation types share the same amortized bound. Structures with multiple operation types that genuinely deserve different amortized costs (for example, a priority queue where `insert` and `delete-min` should be charged differently) are usually analyzed with the accounting method or the potential method instead, both of which generalize the aggregate method's core telescoping idea while allowing per-operation-type bookkeeping.

How does amortized analysis relate to worst-case analysis discussed in earlier foundational material?

Amortized analysis builds directly on the vocabulary of Best, Average, and Worst Case Analysis but changes the unit being bounded: instead of bounding the worst case of a single operation, it bounds the worst case of a sequence of operations and divides by the sequence length. It is still fundamentally a worst-case analysis — over sequences rather than over single calls — which is what makes it deterministic and adversary-proof rather than probabilistic. The proof techniques used, especially the summation and induction underlying the aggregate method, closely parallel the inductive reasoning found in The Substitution Method for solving recurrences.

Before this

Where this leads