首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

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

  • 25-04-21 15:41
  • 4049
  • 8471
juejin.cn

快速选择算法的时间复杂度平均为 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/4 和 n−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

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

注:本文转载自juejin.cn的Tony88的文章"https://juejin.cn/post/7490784514841378866"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

143
阅读
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top