攤還分析

記帳法(accounting method)

把每個操作想成在櫃台付一個固定價錢——它的攤還成本——這價錢可能多於或少於該操作實際做的工。當你多付時,多出的硬幣不會浪費:你把它們存到資料結構上當作預付的存款。之後,當某操作花得比固定價錢多時,它就從先前操作留下的存款裡付差額。這就是記帳法,又稱銀行家法。

你必須永遠維持的紀律是一條不等式:存款餘額絕不能變負。具體地說,你(分析者)為每種操作指派一個攤還費用。然後你驗證:對「任意」序列,攤還費用總和始終至少等於實際成本總和——等價地說,存下的存款在任何時刻都不低於零。若你能證明這點,那麼攤還總成本就是實際總成本的上界,於是你挑的攤還費用有效。訣竅是把費用挑得夠大,使便宜操作存下足夠存款以支付罕見的昂貴操作。對加倍陣列,你可能對每次附加收 3:1 付現在的寫入,多出的 2 存在新元素上,這樣只有自上次擴容後新增的元素帶著存款——當陣列加倍時,那 k/2 個元素各持有 2 個存款,共計恰好 k 個,足夠支付 k 單位的複製。

當你能講清楚哪些便宜操作替哪些昂貴操作買單時,記帳法最出色,而且不像樸素的聚合法,它允許不同操作帶不同費用。要留意的是:你必須對「每條序列的每個前綴」都證明餘額維持非負,而非只在結尾。一個「平均」打平但中途讓存款變負的收費是無效的,因為對手可以恰好在帳目見紅的那一刻停下序列。

加倍陣列,每次附加收 3。在未滿的陣列上附加後,寫入花 1,2 個存款放到新元素上。當大小為 k 的陣列滿了並加倍時,自上次擴容後新增的 k/2 個元素各帶 2 個存款,共 2*(k/2)=k 個——恰好夠付複製當前全部 k 個元素的 k 單位(較舊的一半在上次擴容時已花掉自己的存款)。餘額從不變負,所以每次附加攤還 3 = O(1) 有效。

對便宜操作多收以存下存款;把存款花在罕見的昂貴操作上,並讓餘額始終非負。

有效性取決於存款餘額對序列的每個前綴都維持非負,而非只在結尾。若存款中途可能跌破零,對手就在那裡停下序列,你的攤還界便失效。

又称
banker's method銀行家法記帳分析