中位数选择算法

💡 原文英文,约3100词,阅读约需11分钟。
📝

内容提要

中位数选择算法通过找到未排序数组的中位数来找到未排序数组中第i小的元素。算法的核心思想是找到一个足够好的枢轴,将数组分成两个子数组,其中一个包含第i小的元素。中位数选择算法可以使用主定理进行渐进复杂度分析,并在C++中实现。然而,当数组大小较大时,使用中位数选择算法找到近似中位数可能不是一个好主意。此外,中位数选择算法还可以用于选择问题,即在未排序数组中找到第i小的元素。算法的渐进复杂度为O(N)。

🔎

延伸解读

算法名称的常见误解

中位数选择算法常被误认为直接找到整个数组的中位数,但实际上它是用于在未排序数组中寻找第i小元素的O(N)选择算法。其核心是找到数组的近似中位数作为枢轴进行分区,从而将问题规模缩小。这种近似中位数并不一定是整个数组的中位数,但足以保证分区后第i小元素位于其中一个子数组中。理解这一点有助于正确应用该算法。

近似中位数的质量随数组增大而下降

文章通过数学推导指出,当数组规模N很大时,近似中位数落在数组中的分数范围会变得非常小,即近似中位数可能远离真实中位数。例如,当子数组大小k=5时,分数下界p_i = (3/5)^i - 1/5^i,随着i增大(即N增大),p_i趋近于0。这意味着在大数组上,中位数选择算法找到的枢轴质量可能很差,导致分区不平衡,从而影响实际性能。

渐进复杂度虽为O(N),但常数因子可能很大

尽管中位数选择算法的最坏情况时间复杂度为O(N),但文章强调其渐进常数可能非常大。这是因为算法需要递归地寻找近似中位数,并在每轮分区中排除的元素数量有限。在实际实现中,这种大常数可能导致算法在小规模数据上不如简单的排序选择方法。因此,在数组较大时,使用中位数选择算法寻找近似中位数可能不是一个好主意。

实现细节与测试验证

文章提供了C++实现,包括中位数选择算法和基于排序的选择算法。测试使用一个包含20个整数的向量,中位数选择算法找到的第10小元素为100,与排序选择结果一致。近似中位数函数返回102,接近真实中位数100。这验证了算法的正确性,但也提示在实际应用中需权衡其性能。

❓

Q&A

中位数选择算法的时间复杂度是多少?

中位数选择算法的时间复杂度为O(N),即线性时间。

中位数选择算法的核心思想是什么?

核心思想是找到一个足够好的枢轴(近似中位数),将数组分成两个子数组,其中一个包含第i小的元素,然后递归地在相应子数组中继续查找。

中位数选择算法如何找到近似中位数?

将数组分成大小为k的子数组,对每个子数组排序并找到其中位数,然后递归地对这些中位数调用算法,最终得到整个数组的近似中位数。

中位数选择算法有什么缺点或限制?

当数组规模较大时,找到的近似中位数可能非常差,导致算法在实际中性能不理想;此外,算法的渐进常数可能非常大。

中位数选择算法可以用在哪些场景?

主要用于选择问题,即在未排序数组中找到第i小的元素。

中位数选择算法的最坏情况性能如何?

即使考虑最坏情况,算法的时间复杂度仍为O(N),但渐进常数可能很大,实际性能可能受影响。

🏷️

标签

➡️

继续阅读