The Potential Method

The accounting method tracks credit coin by coin, glued to individual elements. That works, but it can get fiddly: which element holds which credit, and does the bank stay solvent? The potential method is the same idea made elegant and mechanical. Instead of scattering credit across elements, we summarise the entire "stored-up work" of the data structure in a single number — a potential function \Phi, like the potential energy of a stretched spring or the balance of a bank account.

Cheap operations do a little extra work that raises the potential (charging the spring); the rare expensive operation releases that stored potential to pay for itself. It is the most powerful and widely used of the amortisation techniques — the tool of choice for analysing splay trees, Fibonacci heaps, and union–find — precisely because you get to design one clever function and then let the algebra do all the bookkeeping.

The definition, and the telescoping trick

Let D_0 be the initial data structure and D_i the result after the i-th operation, whose actual cost is c_i. Pick any function \Phi that maps a data-structure state to a real number. The amortised cost of operation i is defined to be the actual cost plus the change in potential:

\hat{c}_i \;=\; c_i \;+\; \Phi(D_i) - \Phi(D_{i-1}).

Why is this useful? Sum it over a whole sequence and the potential terms telescope — each \Phi(D_i) appears once with a plus and once with a minus, and everything cancels except the endpoints:

\sum_{i=1}^{n}\hat{c}_i \;=\; \sum_{i=1}^{n} c_i \;+\; \Phi(D_n) - \Phi(D_0).

So the total amortised cost equals the total actual cost, corrected only by the net change in potential from start to finish. Rearranging, the real total we actually care about is

\sum_{i=1}^{n} c_i \;=\; \sum_{i=1}^{n}\hat{c}_i \;-\; \big(\Phi(D_n) - \Phi(D_0)\big).

The one condition that makes it a valid bound

This is exactly the banker's "credit never goes negative" rule, wearing a mathematician's hat: \Phi(D_i) - \Phi(D_0) is the total credit stored in the structure. The potential method just hands you a formula instead of a ledger. The intuition is a spring: as long as the spring never ends up more compressed than it started, all the energy you fed in is available to be spent.

Worked example 1 — the binary counter, elegantly

Take \Phi(D_i) to be simply the number of 1-bits in the counter. It starts at \Phi(D_0) = 0 and is always \ge 0 — the safety condition is free. Now watch a single increment that clears a run of t trailing 1s and sets one 0 to 1:

So n increments cost at most 2n bit-flips — the \Theta(1) amortised bound, with none of the geometric-series bookkeeping. The chart shows the potential \Phi (the number of set bits) rising and falling as the counter runs: it charges up on cheap increments and discharges when a long carry chain fires, but it never drops below its starting value of 0 — which is exactly why the amortised total upper-bounds the real one.

Worked example 2 — a dynamic table that pays for its own resizes

For a growing dynamic array with \text{num} stored items and capacity \text{cap}, choose

\Phi = 2\cdot\text{num} - \text{cap}.

Right after a resize the table is half full (\text{num} = \text{cap}/2), so \Phi = 0 — empty of stored energy. As you push without resizing, \text{num} climbs while \text{cap} stays fixed, so \Phi grows by 2 per push, building up exactly the energy needed. By the time the table is full (\text{num} = \text{cap}), \Phi = \text{cap} — precisely enough stored potential to pay for copying all \text{cap} elements on the next resize.

Same answer as the accounting method (3 per push), but derived by a single well-chosen formula that never needed us to say which element holds which coin. That compression of the bookkeeping into one function is the whole appeal of the potential method.

There is no algorithm for guessing \Phi — it is where the creativity lives, and a badly chosen potential simply gives a useless (or invalid) bound while a good one makes the analysis fall out in one line. The reliable heuristic: \Phi should be large exactly when the structure is in a state that makes the next expensive operation likely, so that the potential is high right before you need to spend it. A binary counter is "dangerous" when it is full of 1s (a long carry looms) — so count the 1s. A dynamic table is dangerous when nearly full — so measure fullness. Splay trees use the log of subtree sizes; Fibonacci heaps count trees plus marked nodes. Find the quantity that spikes just before the pain, and the potential method rewards you.

The telescoping identity is always true — but it only gives an upper bound when \Phi(D_n) \ge \Phi(D_0). If you pick a potential that can fall below its starting value, then \Phi(D_n) - \Phi(D_0) is negative and \sum \hat{c}_i can be smaller than the true total — you would be claiming the sequence is cheaper than it really is, a false bound. This is the potential-method twin of letting the bank go into debt. The safe habit, used almost universally, is to insist \Phi(D_0) = 0 and \Phi(D) \ge 0 for all reachable states; then the endpoint condition holds automatically. Always check this first, before you trust a single amortised number.