算法复杂度分析 (Complexity Analysis)
复杂度分析是评估算法优劣的公理化体系。它不依赖于具体的硬件环境,而是通过数学抽象(大 O 符号)刻画随着输入规模 n 增长时,资源消耗(时间与空间)的渐近增长率。
设 f(n) 为算法的资源消耗函数:
- O(g(n)) (上界):∃c>0,n0>0,∀n≥n0:0≤f(n)≤c⋅g(n)。
- Ω(g(n)) (下界):∃c>0,n0>0,∀n≥n0:0≤c⋅g(n)≤f(n)。
- Θ(g(n)) (等价):f(n)=O(g(n))∧f(n)=Ω(g(n))。
O(1)<O(loglogn)<O(logn)<O(n)<O(n)<O(nlogn)<O(nk)<O(an)<O(n!)
对于分治算法,其复杂度通常遵循递推式:T(n)=aT(n/b)+f(n)。
设 a≥1,b>1 为常数,f(n) 为渐近正函数:
- 若 f(n)=O(nlogba−ϵ),则 T(n)=Θ(nlogba)。 (递归树叶子节点代价占主导)
- 若 f(n)=Θ(nlogbalogkn),则 T(n)=Θ(nlogbalogk+1n)。 (各层代价均衡)
- 若 f(n)=Ω(nlogba+ϵ),且满足正则性条件 af(n/b)≤cf(n) (c<1),则 T(n)=Θ(f(n))。 (根节点代价占主导)
T(n)=∑j=0logbn−1ajf(n/bj)+Θ(nlogba)
递归的收敛性取决于 a(分支因子)与 b(规模缩减因子)的博弈。
当单次操作最坏情况很差,但一系列操作的总和表现良好时使用。
定义势能函数 Φ(D),将数据结构 D 的状态映射为实数。
- 实际代价:ci
- 均摊代价:c^i=ci+Φ(Di)−Φ(D1−1)
∑i=1nci=∑i=1nc^i−(Φ(Dn)−Φ(D0))
若设计合适的 Φ 使得 Φ(Dn)≥Φ(D0),则总实际代价被总均摊代价上界锁定。
递归调用的空间消耗取决于递归深度。
- 平衡分治:深度 O(logn),空间收敛。
- 退化分治:深度 O(n),可能导致栈溢出。
在分治算法中,若子问题的辅助空间在回溯后释放,则总空间复杂度满足 S(n)=S(n/b)+fspace(n)。通过 Case 3 推导,归并排序的空间复杂度为 O(n)。
求解 T(n)=2T(n/2)+nlogn 的渐近复杂度。
Check Solution
- a=2,b=2⟹nlog22=n1。
- f(n)=nlogn=Θ(nlog1n)。
- 符合 Case 2(扩展型),其中 k=1。
- 故 T(n)=Θ(nlog2n)。
证明在随机插入情况下,BST 的平均查找复杂度为 O(logn)。
Check Solution
证明概要:
建立递归式 T(n)=1+n1∑i=0n−1(T(i)+T(n−1−i))。
通过代入法证明其解为 T(n)=O(logn)。这本质上是快速排序划分过程的镜像,利用期望的线性性质实现复杂度收敛。
编者注:复杂度分析不仅是数学工具,更是程序员的“第六感”。它让我们在落笔之前就能预知算法在大规模数据面前的生存能力。