【问题标题】:O(n) algorithm to find the median of n² implicit numbersO(n) 算法找到 n² 隐式数字的中位数
【发布时间】:2011-05-11 05:16:37
【问题描述】:

问题:输入是一个(不一定是排序的)序列 S = k1, k2, ..., kn,有 n 个任意数字。考虑形式为 min{ki,kj} 的 n² 个数的集合 C,其中 1 O(n)时间和O(n)空间算法求C的中位数。

到目前为止,我通过检查不同集合 S 的 C 发现,C 中 S 中最小数的实例数等于 (2n-1),下一个最小数:(2n-3) 等等直到你只有一个最大数量的实例。

有没有办法使用这些信息来找到 C 的中位数?

【问题讨论】:

标签: algorithm median


【解决方案1】:

有多种可能性。我喜欢的是 Hoare 的Select 算法。基本思想类似于快速排序,只是当您递归时,您只递归到将保存您要查找的数字的分区。

例如,如果您想要 100 个数字的中位数,您可以从对数组进行分区开始,就像在快速排序中一样。你会得到两个分区——其中一个包含第 50th 元素。在该分区中递归执行您的选择。继续,直到您的分区仅包含一个元素,这将是中位数(请注意,您可以对您选择的另一个元素执行相同的操作)。

【讨论】:

  • 但是如果C的大小是n^2基于原始序列S有n个数字,那么在C上执行select的运行时间不会是O(n^2)吗?跨度>
  • 抱歉——我没有仔细阅读这个问题。你是对的 - 这与正在搜索的项目数量成线性关系,而不是该集合中唯一项目的数量。
  • 那么我们知道给定重复元素的实例数量这一事实能否以某种方式与选择算法结合使用?
  • 很明显,实现这一点的术语数量少于 n/2,因此我们只进行 n/2 比较。实现这一点所需的项数对应于 i,因此 S 中的第 i 个元素等于 C 的中位数。然后我们可以在 S 上运行 select 以在 O(n) 时间内找到第 i 个元素,因此总运行时间是 O(n)。
  • @domen:是的。如果您确实需要 O(n),您可能希望使用中位数算法的中位数来代替(但请记住,它平均速度较慢,以确保避免在实践中很少出现的最坏情况)。
【解决方案2】:

是的,很好的拼图。我们可以在你所说的线上找到中位数。

在 C 中,max(k) 出现 1 次,次高出现 3 次,次高出现 5 次,依此类推

  1. 如果我们对C的元素排序,第m个最大数左边的元素个数是m^2(奇数之和)

  2. 我们感兴趣的数字(计算中位数) 一种。如果 n 为奇数,则为 (n^2+1)/2 = alpha 湾。如果 n 是偶数,则 alpha1 = n^2/2 和 alpha2 = n^2/2+1 但 alpha1=n^2/2 绝不是平方数 => 紧接在 alpha1 右侧的数字等于 alpha1(前 m 个奇数之和为平方) => alpha1=alpha2。

  3. 所以归结为确定 m 使得 m^2(前 m 个奇数的总和)刚好高于 (n^2/2)

  4. 所以归结为确定 m=ceiling(n/sqrt(2) 和原始序列中的第 m 个最高数。(是否找到第 m 个最高或 (nm-1) 个最低是优化)。

  5. 我们可以很容易地找到第 m 个最高的数字(只需注意左起第一个 m 最大的数字)或使用中位数算法在线性时间内完成。

【讨论】:

    【解决方案3】:

    维基百科有一篇关于Selection algorithms 的好文章。如果您使用 C++,STL 包含一个平均线性时间的 nth_element() 算法。

    【讨论】:

    • @thiagowfx:谢谢,SGI 参考资料非常老旧。
    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    相关资源
    最近更新 更多