§ Amortized analysis



§ Table doubling


§ Aggregate method


We do some sequence of kk operations. Measure the total cost of the kk operations and divide by kk. This defines the amortized cost (Weak definition).

§ Generalized definition (amortized cost)



amortized-cost(op[i])real-cost(op[i]) \begin{aligned} \sum \texttt{amortized-cost}(op[i]) \geq \sum \texttt{real-cost}(op[i]) \end{aligned}


§ 2/3 trees:




O(c+ilogn+dlogn)=O(c+(i+d)logn)[di since we can delete at most number of items]O(c+2ilogn)O(c+ilogn)O(c+ilogn+0d) \begin{aligned} &O(c + i \log n^\star + d \log n^\star) \\ &= O(c + (i + d) \log n^\star) \\ &[\text{$d \leq i$ since we can delete at most number of items}] \\ &\leq O(c + 2i \log n^\star) \\ &\leq O(c + i \log n^\star) &\leq O(c + i \log n^\star + 0d) \end{aligned}

§ Accounting method


Define a time bank account. An operation can store time credit in that bank account. Bank account must always have non-negative time balance. Performing operations costs time. So we can either directly pay for operations, or we can pull money from the time bank account. We can pay for time using the stored credit in the bank.

§ Sid note


On the whole I always find this confusing; Why would I have a bank account if I can also simultaneously pay with an infinite amount of money? So I prefer to think of it as me having (1) an infinitely large, slow, reservoir of gold, (2) a quick cache of gold [which replaces the "bank" ]. To pay for an operation, I can only access money from my quick cache, because pulling money from my slow reservoir is slow. I can transfer money from my infinitely large reservoir to my quick cache of gold. The amortized method calculates the total amount of gold that was pulled from the reservoir and stored into the cache. We might have leftover gold in the quick cache (upper bound). We can't have "negative gold" in the cache. We define the amortized cost to be the total number of gold coins pulled out of infinite reservoir by an operation.

§ Accounting example: 2/3 trees


When we insert, I pull 2log(n)2 \log(n^\star) from my reservoir. I use 1log(n)1 \log(n^\star) to pay for the insertion, and keep a reserve of log(n)\log(n^\star) in the bank. Then when we delete an element, we use the log(n)\log(n^\star) extra we had kept in the cache from the insert.

§ Better bounds: removing the star


We want to say that we pay log(n)\log(n) for insert and delete where nn is the size of the tree when we perform the insert or delete.
Per insert, we pull in two gold coins worth log(n)\log(n) from the reservoir into the cache. When we delete, we use the log(n)\log(n) in the cache from the money that was withdrawn when we created that element. See that the nn changes as the size of the data structure changes.

§ Table doubling via accounting






§ Charging method


Time travel/blame the past for your mistakes. We allow operations to charge their cost retroactively to their past (not to their future!). An operation can withdraw more value that it immediately needs from the infinite reservoir into the gold cache, and it keeps it "for itself" for future-itself.

§ Charging example: Table doubling


After we double the table, the table is half-full, we need to perform n/2n/2 insertions to get the table to be full. When we double the array next time, we charge the doubling to the insertions since the last doubling! There are n/2n/2 items since the last doubling (I had 2 items, I doubled to 4 items, so there are n/2 new items. Now I want to double and add 4 more items). I have a cost of O(n) for the doubling. So I can charge O(1) cost to all the new items since the last doubling. Note that I only charge once; after I've charged items, I've doubled the array, so they are now "old".

§ Potential method (Most powerful) / Defining karma:


We define a potential function ϕ\phi mapping a data-structure-configuration to an natural number pile of gold coins. It tries to measure how bad the datastructure is right now. We can pull money out of the pile of money in the potential. Amortized cost is the actual cost plus the change in the amount of money in the data structure configuration after and before:
amortized(op)=real(op)+ϕ(after(op))ϕ(before(op)) \texttt{amortized(op)} = \texttt{real(op)} + \phi(\texttt{after(op)}) - \phi(\texttt{before(op)})

Adding up all the amortized costs, the sum telescopes, giving us
amortized(total)=real(total)+ϕ(end)ϕ(begin) \texttt{amortized(total)} = \texttt{real(total)} + \phi(\texttt{end}) - \phi(\texttt{begin})


§ Potential example: binary counter


flipping a bit is O(1)O(1). How much will increment cost? An increment is going to cost 1 + the number of trailing ones. We want to make this constant .