Appearance
Master Theorem
- If
, then
证明思路 / 推导过程
对于递推式
- 递归深度:共有
层。 - 每层合并代价(Combine Cost):
。 - 具体到各层代价:
- 第 0 层:
- 第 1 层:
- 第 2 层:
- ...
- 第
层:
- 第 0 层:
总代价:
这是一个公比为
- 若
( ): 数列收敛,总和由第一项(根节点)主导: - 若
( ): 数列发散,总和由最后一项(叶子节点)主导: - 若
( ): 每层代价相等,共有 层:
应用实例:寻找第 k 小的数 (QuickSelect)
使用快排(QuickSort)的思路:先进行一次 Partition,找到第 1 个位置
1. 最坏情况 (Worst Case)
如果每次选出的 pivot 只能筛掉一个元素(例如数组已排序且选第一个元素为 pivot):
这种情况非常糟糕。
2. 平均情况 (Average Case)
我们可以通过概率分析来观察平均性能。定义“好运气”和“坏运气”:
- Good luck:划分后的子问题规模
。 - Bad luck:划分后的子问题规模
。
在随机选择 pivot 的情况下,落在中间
推导过程: 设
递归期望代价:
展开级数:
由于这是一个公比为
结论:QuickSelect 的平均时间复杂度为
3. 如何选择一个好的 Pivot? (Median of Medians)
随机化分析的缺点: 随机性太强,虽然期望是
我们希望寻找一种确定性的方法来选择 pivot,使得:
启发式方法:中位数的中位数 (BFPTR 算法)
- 将
个数分为 组,每组 5 个数。 - 找出每组的中位数,总耗时
。 - 递归地找出这
个中位数的中位数,记为 。此步骤代价为 。
Pivot 的质量保证
根据“中位数的中位数”的性质,至少有
由此得到递推式:
复杂度证明
方法一:递归树分析
- Level 0:
- Level 1:
- Level 2:
- ...
- Level
:
总代价为公比为
方法二:归纳法 (代入法) 假设
若要满足
实际评价: 虽然理论上是确定的
4. 深入讨论:为什么选择 5 作为分组大小?
在 BFPTR 算法中,分组大小
(1) 为什么选择奇数?
选择奇数是因为在对每组进行排序后,中位数是唯一的(即正中间的那个位置)。如果选择偶数(如 4 或 6),则需要规定取左中位数或右中位数,增加了逻辑复杂度。
(2) 为什么是 5 而不是 3?
从递推式出发,设分组大小为
- 寻找中位数的中位数需要
。 - 划分后,根据“中位数的中位数”的几何性质,能够排除的元素个数约为
。 - 剩余的子问题规模为
。
得到递推式:
为了使
解不等式:
- 若
:系数之和 。此时递推式变为 ,无法达到线性复杂度。 - 若
:系数之和 。这是满足线性复杂度的最小奇数。
(3) 为什么是 5 而不是 7 或更大?
虽然从数学上看,
- 递归子问题的规模(随
增大而减小)。 - 寻找每组中位数的时间开销(随
增大而显著增加)。
开销分析:
- 当
时:寻找 5 个数的中位数非常快,只需要最多 6 次比较。 - 当
时:寻找 7 个数的中位数所需的比较次数和操作复杂度会显著上升。
随着
结论: 5 是一个“甜点位” (Sweet Spot):它既保证了递推式系数之和小于 1(打破了
因此,5 是在平衡“排除效率”与“算法常数”后的最优选择。