势能分析法
势能分析法
势能分析通过定义一个势能函数(通常表示为
——摘自 OI-wiki
原理
定义状态
其次,定义的势能函数
- 初始势能:
。 - 非负性:任意状态下
。
Ps:也有说法表示不必满足以上性质,势能函数反映数据结构变化量即可。
对于每个操作,均摊成本
其中
该公式表明均摊成本等于实际成本加势能变化量。
有一种理解方式是:当
我们通过势能函数来分析一系列操作的总成本。
例题:动态数组的扩容分析
题面
初始时数组大小为
若不计开新数组的时间,单次插入
分析
设数组长度为
-
插入操作(不扩容)
操作成本:
。势能变化:
, 。均摊成本:
。 -
插入操作(扩容)
操作成本:
。势能变化:
, 。均摊成本:
。
此处看出虽然扩容操作成本高,但势能变化量减小;反之同理。整体均摊在
实践:分析 Splay 树的复杂度
定义
势能变化量为
由于
根据子树大小关系推导的
观察上面的树,不难发现有
于是我们可以得到(注意与上面的式子不同)
于是均摊势能为
首先还是分析势能变化量
观察上图,可得
同理可得
于是有
综上,1.2. 两种操作均摊为 splay
是若干次 1.2. 操作与一次 3. 操作的结合,所以一次 splay
的代价为
由于其他操作都是基于 splay
,在势能函数中以常数的形式体现,于是我们可以估计一棵 Splay 树的平均复杂度是
根据上面的分析
再根据势能函数的定义,有
代入原式
Q.E.D.
习题
栈问题
一个栈,有以下 3 种操作:
- 入栈
- 弹出栈顶元素
- 在栈顶弹出若干元素
通过均摊分析其复杂度。
二进制加法计算器
有一个二进制加法计算器,在 1111+1
时会改变五个数字的值,修改的数字最多达到 +1
是
序列 GCD
给出一个有
gcd(a,b) = if b==0 return a;
else return gcd(b,a%b)
int main()
ans = a[1]
for(int i=2; i<=n; ++i)
ans = gcd(ans,a[i])
求这个算法的时间复杂度,并给出证明。
习题解析
栈问题
设势能函数
。
仅入栈时均摊复杂度为
二进制加法计算器
设势能函数
-
相加不进位
-
相加进位
均摊复杂度为
序列 GCD
设势能函数
-
求完一次后 gcd 不改变
-
求完一次后 gcd 改变
由于势能函数小于
时间复杂度为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!