【问题标题】:Complexity of finding k-th largest element using Median of Medians使用中位数的中位数找到第 k 个最大元素的复杂性
【发布时间】:2012-09-14 20:01:24
【问题描述】:

我正在阅读有关通过median-of-medians 算法在ardendertat 查找数组中第k 个最高元素的文章。在解释复杂性的部分,作者似乎忽略了一个因素,即递归查找每个分区的median-of-medians 的成本。当然,我不能按初始枢轴对所有子阵列进行分区,对吧?那么这不会增加复杂性吗?

【问题讨论】:

  • 找到中位数的成本是线性的。
  • 是的,但是我们必须在每个递归调用中对每个分区都这样做,对吧?那么这不会加起来吗?
  • 关于分区工作本身也可以问同样的问题,这也是线性的。但你不是问它,为什么?
  • 嗯,我不知道!实际上现在我发现我根本不理解复杂性方程!如果你能解释清楚一点,那将是非常有帮助的。

标签: python algorithm median-of-medians


【解决方案1】:

中位数算法是为快速选择算法开发的,它与快速排序非常相似,但实际上是线性的,而不是 O(n log n),因为它只在分区的一侧递归。选择问题是选择集合 S 中第 kth 个最大的元素;求中位数是 k = (|S| + 1)/2 的特例。

算法很简单:

  • 选择一些枢轴值,p.

  • 将元素分成两组:S(所有元素 ≥(所有元素 ≥ p)。

  • 递归:如果S至少为k,则求S中第kth个最大元素;否则,在 S 中找到 (k - |S|)th 个最大元素。

与快速排序一样,关键是找到枢轴值。我们将按如下方式进行:

  • 构造Smedians,由S的每组5个元素的中位数组成。

  • 通过递归调用 select 找到 Smedians 的准确中位数。

现在,|S中位数|正好是 0.2 * |S|。此外,一旦我们有了基准,我们就知道 max(|S|, |S) ≤ 0.7 * |S|。 [fn 1] 所以对 select 的两次递归调用总和为 0.9 * |S|。

所以我们现在可以证明计算 select 的时间与 Σ0.9i n 成正比,这显然与 n 呈线性关系。

我希望这对你来说已经足够清晰了。


如果不明显,Smedians 中的一半中位数必须至少为 p(因为 p 是它们的中位数),并且对于与这些中位数相对应的每组 5 个,三个五个元素中的一个(中位数和两个较大的元素)必须至少为 p。所以这是 S 中总元素的 50% 的 60%,或 30%。一个类似的论点适用于用“最多”代替“至少”,所以我们知道两个子集中较小的一个至少是 S 大小的 30%,因此较大的一个最多是大小的 70%。

【讨论】:

    【解决方案2】:

    对数组进行分区后中位数的中位数p的位置在0.3*n0.7*n之间。

    所以一轮之后,我们有三种可能:

    1. p == n-k,幸运的是,第一个枢轴是k-th 最大的元素,在 O(n) 中找到(中位数的中位数和分区都是 O(n))。
    2. p > n-k,那么k-th最大元素小于第一个pivot,我们需要找到第一部分的k - (n-p)-th最大元素,最多有0.7*n元素,所以找到k-th 最大元素的总成本是

      T(n) <= T(0.7*n) + C*n
      
    3. p &lt; n-k,那么我们需要找到第二部分(pivot之后)的k-th最大元素,该部分也最多0.7*n元素大,所以我们再次进行估算

      T(n) <= T(0.7*n) + C*n
      

    迭代,我们发现

    T(n) <= T((0.7)^k * n) + C*(1 + 0.7 + ... + (0.7)^(k-1))*n
         <= T(1) + C/(1 - 0.7)*n
    

    显然是 O(n)。

    【讨论】:

      猜你喜欢
      • 2014-05-20
      • 2015-06-22
      • 1970-01-01
      • 1970-01-01
      • 2018-09-13
      • 1970-01-01
      • 2016-09-04
      • 1970-01-01
      • 2022-01-23
      相关资源
      最近更新 更多