【发布时间】:2016-04-06 08:38:33
【问题描述】:
Wikipedia lists the median-of-medians algorithm as requiring O(1) auxiliary space.
但是,在算法的中间,我们对大小为n/5 的子数组进行递归调用以找到中位数的中位数。当这个递归调用返回时,我们使用返回的中位数作为基准对数组进行分区。
这个算法不是将O(lg n) 激活记录作为递归的一部分推送到运行时堆栈吗?据我所知,这些寻找中位数的连续中位数的递归调用不能进行尾调用优化,因为我们在递归调用返回后做了额外的工作。因此,该算法似乎需要O(lg n) 辅助空间(就像快速排序一样,由于运行时堆栈使用的空间,维基百科将其列为需要O(lg n) 辅助空间)。
是我遗漏了什么,还是维基百科的文章有误?
(注意:我指的递归调用是维基百科页面上的return select(list, left, left + ceil((right - left) / 5) - 1, left + (right - left)/10)。)
【问题讨论】:
-
@Nuclearman 这是一个公平的观点,但是
pivot函数会调用select,,所以我们不能忽略select所需的空间。 Wikipedia 文章将这两个函数描述为相互递归。如果我们忽略对select的调用,我们最终不会得到中位数的中位数。相反,我们最终得到n/5中位数为 5。 -
@Nuclearman Quickselect 不需要堆栈,因为它可以进行尾调用优化。它可以进行尾调用优化,因为我们在递归中基本上只遍历一个从根到叶的路径。我们不需要记住我们的历史。 Median-of-medians 不能以相同的方式优化,因为它在每个级别都有多个递归调用。换句话说,我们在算法执行期间遍历了多个从根到叶的路径。我们需要记住我们的历史,这样当我们到达一片叶子时,我们就知道该往哪里回去。我们不能在恒定空间中进行这样的遍历。
-
@John 我目前也在处理这个问题,并且同意你的所有观点。我 asked the author 维基百科的 O(1) 声明,希望我们能得到答案。
-
@StefanPochmann 谢谢斯特凡。我首先根据 Leetcode 的 Wiggle Sort II 开始对此进行调查,您似乎也在查看 :) 感谢您与原作者联系。不知道这是一个选择!
-
@John 是的,leetcode 也是如此。我几乎可以肯定这不是巧合。但巧合的是,您当前的 3137 点是 1337 的字谜 :-)
标签: algorithm recursion space-complexity median-of-medians