【问题标题】:finding running medium from a stream从流中寻找正在运行的介质
【发布时间】:2015-10-20 08:31:14
【问题描述】:

问题:假设整数是从数据流中读取的。以有效的方式查找到目前为止读取的元素的中位数。

我找到了解决方案here

我的问题是为什么我们需要使用堆而不是简单地将数字添加到向量中?

例如,假设我们使用一个向量来存储传入的数据,那么我们调用该方法计算中位数如下:

if vector size is even
   return (element at size/2 + element at size/2-1);
else
   return (element at size/2);

上述解决方案是否有效?

【问题讨论】:

    标签: algorithm median


    【解决方案1】:

    如果向量中的元素不按顺序排列,您的解决方案将无法工作。如果在向量的末尾添加元素,它们将不会按顺序排列。

    另一方面,堆中的元素是有序的。

    另外,第一个 return 语句中缺少二除。

    【讨论】:

    • 感谢您的澄清!不确定是否正确,但据我了解,假设您有 n 个来自数据流的整数;因为将元素插入堆需要 o(lg(n)),所以总时间复杂度为 o(nlg(n))。另一方面,我们可以先将数据插入到一个需要线性时间的向量中,然后调用排序算法,该算法也是 o(nlg(n))。因此,对于这个问题,我并没有真正看到使用复杂数据结构的优势。
    • 不同之处在于,如果您每次要计算中位数时都对向量进行排序,那么您就是在做额外的工作,因为您没有利用已经排序的元素。考虑这种情况:从流中获取 n 项,计算中位数,再获取一项,再次计算中位数。对于堆,你有 O(nlogn) + O(logn) + O(logn) + O(logn)。使用向量,您有 O(n) + O(nlogn) + O(1) + O(nlogn)。因此,除了内存问题,这取决于您希望计算中位数的频率。
    【解决方案2】:

    您提出的解决方案未被普遍使用至少有两个原因:

    1. 一般来说,如果您正在处理一个数据流,该流是巨大的甚至是无限的,因此存储所有值是不切实际的。
    2. 正如@ChronoTrigger 所说,您必须对向量进行排序才能使用它。该问题通常假设您希望能够一遍又一遍地请求中值作为新数据流。为了使用您的解决方案做到这一点,您必须一遍又一遍地对向量进行排序,这会很慢。

    总体而言,很难有效地维护流数据集的准确中值。有许多算法可以做到这一点,但它们都会做出权衡,比如降低准确度以降低内存使用率等。

    【讨论】:

    • 谢谢奥利弗!我看到您不断对向量进行排序的观点,但是,对于堆方法,我们还不需要存储整个数据流吗?
    • 是的,对于堆方法,您仍然需要存储整个流。请注意,您链接的 SO 帖子的第一个回复谈到了该方法的内存问题。
    【解决方案3】:

    Vector 仅在您将新元素添加到适当位置(根据排序顺序)时才有效。

    例如: 流:8 3 4 1 10 12

    如果您只是在向量末尾继续添加元素,则每一步的中位数:

    step 1: vector: 8 median: 8
    step 2: vector: 8, 3 median: (8+3)/2
    step 3: vector: 8, 3, 4 median: 3 (when actually it should be 4)
    

    希望你能明白

    【讨论】:

      猜你喜欢
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-12
      • 1970-01-01
      相关资源
      最近更新 更多