快速选择算法的时间复杂度分析

快速选择算法的时间复杂度平均为 O(n) 的核心原因在于其每次递归的问题规模呈几何级数递减。以下是详细的推导过程:


一、直观理解

假设每次分区操作能将数组大致分成两半(例如:每次丢弃约一半元素),则时间复杂度可表示为:

scss 复制代码
T(n) = T(n/2) + O(n)

根据主定理(Master Theorem),这个递推关系的解为 O(n)

但实际情况更复杂,因为每次分区的比例是随机的。我们需要通过概率期望来严格证明。


二、数学推导(期望值法)

1. 定义变量

T(n) 为处理规模为 n 的数组的期望时间复杂度。

2. 分区过程分析

每次选择pivot后,数组被分为三部分:

  • > pivot 的元素数量:假设为 m
  • = pivot 的元素数量:假设为 c
  • < pivot 的元素数量:假设为 n−m−c

此时递归只需要处理其中一个分区:

  • 若目标在第 > 分区,递归规模为 m
  • 若目标在 = 分区,直接返回
  • 若目标在 < 分区,递归规模为 n−m−c

3. 递推公式

根据期望的线性性:

scss 复制代码
T(n) = O(n) + E[T(递归规模)]

其中 O(n) 是分区的操作时间,E[...] 是期望。

由于pivot是随机选择的,每个元素被选为pivot的概率相等。可以证明:

scss 复制代码
E[递归规模] ≤ (3/4)n

(证明见下文*)

4. 递推展开

代入期望递归规模:

scss 复制代码
T(n) ≤ O(n) + T(3n/4)

展开递推:

scss 复制代码
T(n) ≤ O(n) + O(3n/4) + O((3/4)^2 n) + ... 

这是一个几何级数,总和为:

scss 复制代码
T(n) ≤ O(n) * (1 + 3/4 + (3/4)^2 + ...) = O(n) * 4 = O(n)

三、关键证明:为什么 E[递归规模] ≤ (3/4)n

1. 随机化pivot的优势

当pivot随机选择时,有至少 50% 的概率将数组分成至少 1:3 的比例。更准确地说:

  • 至少 50% 的pivot会将数组分为 m ≤ 3n/4n−m−c ≥ n/4
  • 无论选择哪一侧递归,递归规模最多为 3n/4

2. 概率加权计算

每次分区后,递归规模的期望:

scss 复制代码
E[递归规模] ≤ (概率选择较大侧)*规模 + (概率选择较小侧)*规模

通过对称性分析可得:

scss 复制代码
E[递归规模] ≤ (1/2)*(3n/4) + (1/2)*(3n/4) = 3n/4

四、对比快速排序

快速排序需要处理两个分区,递推式为:

scss 复制代码
T(n) = 2T(n/2) + O(n) → O(n log n)

而快速选择只需处理一个分区 ,因此时间复杂度降为 O(n)


五、总结

  • 平均时间复杂度:O(n)(由几何级数递减保证)
  • 最坏时间复杂度:O(n²)(当每次分区都极不平衡时,但概率极低)
  • 核心优势:随机化pivot将问题规模以几何级数缩减

这种时间复杂度分析方式体现了随机化算法的威力:通过概率避免最坏情况,使得平均性能极佳。

一、关于「50%概率分成至少1:3比例」的详细推导


核心概念:分位点选择

当随机选择一个pivot时,该元素在排序后的数组中的位置是均匀分布的。我们可以将数组分为四个等长的区域:

css 复制代码
[0%-25%] [25%-50%] [50%-75%] [75%-100%]

关键观察 :若pivot落在中间的50%区域(即25%到75%分位之间),则分区后的左右两侧都会不超过原数组长度的3/4

• 例如:当pivot是第30%小的元素时: ◦ 左侧(≤ pivot)占30%,右侧(> pivot)占70% → 最大分区规模为70% ≈ 0.7n < 0.75n • 同理,当pivot是第70%小的元素时,最大分区规模为70%n

概率计算

• 中间50%区域的总长度:75% - 25% = 50%

概率pivot落在中间50%区域 :50%

此时无论选择左半区还是右半区,递归处理的规模最大为3n/4

可视化解释

perl 复制代码
原始数组长度:n
如果pivot落在中间50%区域:
    ≤ pivot的元素数 ∈ [25%n, 75%n]
    > pivot的元素数 ∈ [25%n, 75%n]
无论选择哪一侧,递归处理的规模 ≤ 75%n = 3n/4

因此,每次递归有至少50%的概率将问题规模缩减到≤3n/4


二、几何级数求和的详细推导


递推关系

假设每次递归处理的规模为前一次的 3/4,时间消耗为:

scss 复制代码
T(n) = T(3n/4) + O(n)

展开递推式

将递推式逐层展开:

scss 复制代码
T(n) = O(n) + T(3n/4)
     = O(n) + O(3n/4) + T((3/4)^2 n)
     = O(n) + O(3n/4) + O((3/4)^2 n) + T((3/4)^3 n)
     ...

几何级数求和

观察每一层的系数:

scss 复制代码
总和 = n + (3/4)n + (3/4)^2 n + (3/4)^3 n + ...

这是一个首项为 a = n ,公比 r = 3/4 的无限几何级数。

几何级数求和公式:

scss 复制代码
总和 = a / (1 - r) = n / (1 - 3/4) = n / (1/4) = 4n

因此总时间复杂度为 O(4n) = O(n)

直观理解递减速度

• 每次递归规模以 3/4 的速度指数级衰减 • 递归深度为 log_{4/3} n(例如n=64时深度≈7层) • 各层时间相加收敛到4n


三、严格数学证明(可选补充)

对于更严谨的证明,可以用期望的线性性(Linearity of Expectation):

设每次分区成本为 c·n ,递归次数期望为 E,则:

r 复制代码
E[T(n)] = c·n + E[T(递归规模)]

由于每次递归有至少50%概率将规模降至3n/4,可得:

less 复制代码
E[T(n)] ≤ c·n + 0.5·E[T(3n/4)] + 0.5·E[T(n)]  // 50%概率处理3n/4,50%可能更差

解此不等式可得:

r 复制代码
E[T(n)] ≤ 2c·n + E[T(3n/4)]

进一步展开后仍收敛到 O(n)


总结

  1. 概率保证:随机化pivot使得每次有50%概率将问题规模降至≤3n/4
  2. 几何级数衰减:递归成本总和收敛到线性时间复杂度
  3. 实际意义:快速选择的平均性能远优于最坏情况,是工程实践中的高效选择

递归规模数学期望的严格推导

为了深入理解快速选择算法的时间复杂度分析,我们需要从概率论的角度严格推导递归规模的期望。以下是分步推导过程:


1. 模型设定

• 设数组有 n 个互不相同的元素(简化分析,可推广到重复元素) • pivot随机选择 :每个元素被选为pivot的概率为 1/n • 定义 递归处理的问题规模 为随机变量 X

2. 递归规模的概率分布

假设需要找第 k 大的元素,根据分区后的情况: • 若 k ≤ m (左段元素数),递归处理左段,规模为 m • 若 k > m + c (右段元素数),递归处理右段,规模为 n - m - c • 否则直接返回pivot

在快速选择中,每次递归只需要处理一侧分区。为简化推导,我们分析最坏情况下的递归规模期望(即总是处理较大的一侧)。

3. 关键观察:对称性

由于pivot是随机均匀选择的,当不考虑k的具体位置时,左段规模m和右段规模n−m−1的概率分布是对称的。因此:

css 复制代码
E[X] = E[max(m, n−m−1)]

其中 m 是pivot的排名减1(即左段元素数),服从均匀分布 m ~ Uniform{0, 1, ..., n−1}

4. 计算 E[max(m, n−m−1)]

对于每个可能的 m ,计算对应的 max(m, n−m−1) : • 当 m ≥ (n−1)/2 时,max(m, n−m−1) = m • 当 m < (n−1)/2 时,max(m, n−m−1) = n−m−1

由于对称性,可以只计算前半部分并加倍:

ini 复制代码
E[X] = (2/n) * ∑_{m=⌈(n-1)/2⌉}^{n−1} m

具体计算(分奇偶情况):

当n为奇数:设n=2k+1

scss 复制代码
E[X] = (2/(2k+1)) * ∑_{m=k}^{2k} m
      = (2/(2k+1)) * [k + (k+1) + ... + 2k]
      = (2/(2k+1)) * (3k² + 3k)/2
      = (3k² + 3k)/(2k+1) ≈ (3/4)n

当n为偶数:设n=2k

scss 复制代码
E[X] = (2/(2k)) * ∑_{m=k}^{2k−1} m
      = (1/k) * [k + (k+1) + ... + (2k−1)]
      = (1/k) * (3k² - k)/2
      = (3k−1)/2 ≈ (3/4)n

综上可得:E[X] ≈ (3/4)n


5. 递推关系的建立

T(n) 为处理规模n的期望时间复杂度,每次递归包含: • 分区操作 :时间复杂度 O(n)递归处理子问题 :期望时间 T(E[X])

根据期望的线性性:

scss 复制代码
E[T(n)] = O(n) + E[T(X)]

代入 E[X] ≈ (3/4)n

r 复制代码
E[T(n)] ≤ c·n + E[T(3n/4)]

6. 递推展开

将递推式展开为几何级数:

r 复制代码
E[T(n)] ≤ c·n + c·(3n/4) + c·(3n/4)² + ... 
        = c·n [1 + 3/4 + (3/4)² + ...]

这是一个首项为1,公比为3/4的无限几何级数,其和为:

ini 复制代码
Sum = 1 / (1 − 3/4) = 4

因此:

ini 复制代码
E[T(n)] ≤ 4c·n = O(n)

7. 严格概率证明(使用鞅论)

更严谨的证明需要用到停时理论 (Optional Stopping Theorem): • 定义随机过程 S_t = (3/4)^t·n_t ,其中 n_t 是第t次递归的问题规模 • 验证 S_t 是上鞅(Supermartingale):

scss 复制代码
E[S_{t+1} | S_t] = (3/4)^{t+1}·E[n_{t+1} | n_t] 
                 ≤ (3/4)^{t+1}·(3/4)n_t 
                 = (3/4)·S_t ≤ S_t

• 根据停时定理,期望停时 E[T] 满足:

ini 复制代码
E[S_T] ≤ S_0 = n

当递归终止时 n_T = 1,故:

css 复制代码
E[(3/4)^T·1] ≤ n ⇒ E[(3/4)^T] ≤ n

取对数得:

scss 复制代码
E[T] ≤ log_{4/3}(n) + C

因此总时间复杂度:

r 复制代码
E[总时间] = ∑_{t=0}^{T} c·(3/4)^t·n ≤ c·n·∑_{t=0}^∞ (3/4)^t = 4c·n

总结

  1. 对称性分析:利用pivot的均匀分布特性,将递归规模期望转化为对称积分问题
  2. 递推展开:通过几何级数求和得出线性时间复杂度
  3. 停时理论:严格证明递归过程的期望终止时间

这种分析展示了随机化算法在避免最坏情况上的威力,通过概率期望将看似不稳定的操作转化为高效的平均性能。

数学符号与求和的详细解释


变量定义与模型设定

假设数组长度 n 为奇数,令 n = 2k + 1 (例如 n=7 对应 k=3)。

定义 m 为分区后左段的元素个数(即严格大于 pivot 的元素数量),其取值范围为 m ∈ {0, 1, ..., 2k}

由于 pivot 是均匀随机选择的,m 的概率分布为:

scss 复制代码
P(m) = 1/(2k+1), ∀ m ∈ {0, 1, ..., 2k}

递归规模的定义

在快速选择算法中,每次递归处理的是问题规模较大的分区。

定义递归规模 X 为:

scss 复制代码
X = max(m, n−m−1) = max(m, 2k−m)

(因为 n−m−1 = (2k+1)−m−1 = 2k−m


期望值的计算

根据期望定义:

scss 复制代码
E[X] = ∑_{m=0}^{2k} max(m, 2k−m) * P(m)

由于对称性(max(m, 2k−m) = max(2k−m, m)),可以将求和范围缩减为一半:

ini 复制代码
E[X] = 2 * ∑_{m=k}^{2k} m * P(m)

(当 m ≥ k 时,max(m, 2k−m) = m;当 m < k 时,max(m, 2k−m) = 2k−m,与右侧对称)

具体展开:

ini 复制代码
E[X] = 2/(2k+1) * ∑_{m=k}^{2k} m

求和的上下界与变量说明

  1. 求和符号 :∑_{m=k}^{2k} m

    下界 :m = k

    上界 :m = 2k

    变量:m 是左段元素数量,从 k 到 2k

  2. 求和项的意义

    当 m 从 k 增加到 2k 时,左段规模逐渐增大,右段规模逐渐减小。

    例如:

    • 当 m = k 时,右段规模为 2k−k = k

    • 当 m = 2k 时,右段规模为 2k−2k = 0

  3. 几何意义

    该求和计算的是所有可能左段规模 ≥ k 的情况,且每个项的权重相等(概率 1/(2k+1))。


求和的具体计算

展开求和式:

ini 复制代码
∑_{m=k}^{2k} m = k + (k+1) + (k+2) + ... + 2k

这是一个等差数列,首项为 k,末项为 2k,项数为 (2k − k + 1) = k + 1。

根据等差数列求和公式:

scss 复制代码
Sum = (首项 + 末项) * 项数 / 2  
     = (k + 2k) * (k+1) / 2  
     = (3k)(k+1)/2

代入期望表达式:

scss 复制代码
E[X] = 2/(2k+1) * [3k(k+1)/2]  
      = (3k(k+1)) / (2k+1)

渐近行为分析

n → ∞(即 k → ∞)时,用斯特林近似:

scss 复制代码
3k(k+1)/(2k+1) ≈ 3k²/(2k) = (3/2)k = (3/4)(2k+1) = (3/4)n

因此,E[X] ≈ 3n/4


几何级数求和推导

假设每次递归后问题规模以 3/4 的比例缩减,总时间复杂度可展开为:

scss 复制代码
T(n) = O(n) + T(3n/4)  
      = O(n) + O(3n/4) + T((3/4)^2 n)  
      = O(n) * [1 + (3/4) + (3/4)^2 + ...]

这是一个无限几何级数,其中: • 首项 a = 1

公比 r = 3/4

根据几何级数求和公式:

ini 复制代码
Sum = a / (1 − r) = 1 / (1 − 3/4) = 4

因此:

scss 复制代码
T(n) = O(n) * 4 = O(n)

完整公式总结

步骤 公式 说明
递归规模期望 E[X] = 2/(2k+1) ∑_{m=k}^{2k} m 对称性简化后的求和式
等差数列求和 ∑_{m=k}^{2k} m = 3k(k+1)/2 等差数列首项 k,末项 2k
渐近近似 E[X] ≈ 3n/4 当 n → ∞ 时
时间复杂度 T(n) = O(n) * ∑_{t=0}^∞ (3/4)^t = O(4n) 几何级数求和

可视化验证

n=7(k=3)为例:

ini 复制代码
∑_{m=3}^{6} m = 3+4+5+6 = 18  
E[X] = 2/7 * 18 ≈ 5.14  
理论近似值:3n/4 = 5.25  
误差仅 2%,验证公式合理性。

通过这种严格的数学推导,可以清晰地看到快速选择算法的时间复杂度是如何被控制在 O(n) 的。

严格数学分析:递归规模期望的精确性


一、核心矛盾澄清

你在观察中发现的「≤3n/4」与「≈3n/4」的差异,本质上是两种不同分析视角的体现:

  1. 概率上界分析 :给出保守的 E[X] ≤ 3n/4(对所有n成立)
  2. 渐近近似分析 :实际 E[X] = (3/4)n − Θ(1)(精确值略小于3n/4)

二、严格数学证明

1. 有限n的精确期望

n=2k+1(奇数)为例,通过精确计算:

scss 复制代码
E[X] = (3k² + 3k) / (2k+1) = (3k(k+1)) / (2k+1)

展开后:

scss 复制代码
E[X] = (3/4)(2k+1) − 3/(4(2k+1)) = (3/4)n − 3/(4n)

因此 E[X] = (3/4)n − Θ(1/n),严格小于3n/4。

2. 渐近行为

n→∞ 时:

ini 复制代码
lim_{n→∞} E[X]/n = 3/4

E[X] ≈ 3n/4 在渐近意义下成立。

3. 概率加权分析的保守性

原证明中的结论 E[X] ≤ 3n/4 是保守上界,实际: • 严格不等式 :E[X] < 3n/4(对所有有限n) • 渐近等价:E[X] ~ 3n/4(当n→∞)


三、两种分析方法的统一

分析方法 结论 适用范围 严谨性
对称性+精确计算 E[X] = (3/4)n − Θ(1/n) 有限n 精确但复杂
概率上界(50%规则) E[X] ≤ 3n/4 所有n 保守但简洁

为什么原证明使用3n/4?

  1. 简化时间复杂度分析:几何级数求和需要明确的上界
  2. 兼容所有情况:包括奇偶n和边界条件
  3. 工程实践:保守估计足够证明O(n)复杂度

四、具体案例验证

案例1:n=7 (k=3)

• 精确计算:

ini 复制代码
E[X] = (3*3*4)/7 = 36/7 ≈ 5.14 < 3*7/4 = 5.25

• 误差:≈2.1%

案例2:n=1001 (k=500)

• 精确计算:

ini 复制代码
E[X] = (3*500*501)/1001 ≈ 751.2 < 3*1001/4 = 750.75

矛盾? 实际计算值751.2 > 750.75,说明上述推导有误?

修正推导(关键发现)

原推导中的误差项应为:

scss 复制代码
E[X] = (3/4)n − 3/(4(2k+1)) = (3/4)n − 3/(4n)    (当n=2k+1时)

对于n=1001(k=500):

scss 复制代码
E[X] = (3/4)*1001 − 3/(4*1001) ≈ 750.75 − 0.00075 ≈ 750.74925

实际精确计算应为:

ini 复制代码
E[X] = (3*500*501)/1001 = 751500/1001 ≈ 750.74925

与修正后的公式一致,严格小于3n/4=750.75。


五、结论

  1. 严格不等式:对所有有限n,E[X] < 3n/4
  2. 渐近等价性:当n→∞时,E[X]/n → 3/4
  3. 原证明的合理性:使用3n/4作为上界是安全的,且足够证明时间复杂度为O(n)

可视化总结

scss 复制代码
        E[X]
        /\
        | 3n/4 (渐近线)
实际曲线 ↗ 
        |严格低于3n/4
        |------------------> n

这种微妙的差异反映了理论计算机科学中常见的权衡:为了简化分析,接受一个略微宽松但安全的上界,而不是追求完全精确但复杂的表达式。

相关推荐
Dovis(誓平步青云)27 分钟前
【数据结构】励志大厂版·初阶(复习+刷题):复杂度
c语言·数据结构·经验分享·笔记·学习·算法·推荐算法
Jerry说前后端30 分钟前
2025年第十六届蓝桥杯省赛C++ 研究生组真题
c++·算法·蓝桥杯
小文数模35 分钟前
2025年认证杯数学建模竞赛A题完整分析论文(含模型、可运行代码)(共32页)
算法·数学建模·matlab
LuckyLay1 小时前
LeetCode算法题(Go语言实现)_45
算法·leetcode·golang
君义_noip1 小时前
信息学奥赛一本通 1498:Roadblocks | 洛谷 P2865 [USACO06NOV] Roadblocks G
c++·算法·图论·信息学奥赛
小羊在奋斗1 小时前
【今日三题】经此一役小红所向无敌(模拟) / 连续子数组最大和(动态规划) / 非对称之美(贪心)
算法·动态规划
杜小暑1 小时前
字符串与相应函数(下)
c语言·开发语言·算法
阳洞洞2 小时前
leetcode 139. Word Break
算法·leetcode·word·动态规划
try to be better_fly2 小时前
buctoj_算法设计与分析(5)
算法