一尘不染

面试问题:从整数整数中查找中位数

algorithm

有一个文件,其中包含10G(1000000000)个整数,请找到这些整数的中位数。您将获得2G内存来执行此操作。任何人都可以提出合理的方法吗?谢谢!


阅读 267

收藏
2020-07-28

共1个答案

一尘不染

创建一个具有2 ^ 16项的8字节长数组。输入您的输入数字,移出最低的16位,然后创建直方图。

现在,您可以在该直方图中进行计数,直到到达覆盖值中点的区域。

再次通过,忽略所有没有相同的最高位集合的数字,并对最低位进行直方图绘制。

计数直方图,直到到达覆盖值(整个列表)中点的区域。

现在您知道了O(n)时间和O(1)空间的中位数(实际上,不到1 MB)。

这是一些执行此操作的示例Scala代码:

def medianFinder(numbers: Iterable[Int]) = {
  def midArgMid(a: Array[Long], mid: Long) = {
    val cuml = a.scanLeft(0L)(_ + _).drop(1)
    cuml.zipWithIndex.dropWhile(_._1 < mid).head
  }
  val topHistogram = new Array[Long](65536)
  var count = 0L
  numbers.foreach(number => {
    count += 1
    topHistogram(number>>>16) += 1
  })
  val (topCount,topIndex) = midArgMid(topHistogram, (count+1)/2)
  val botHistogram = new Array[Long](65536)
  numbers.foreach(number => {
    if ((number>>>16) == topIndex) botHistogram(number & 0xFFFF) += 1
  })
  val (botCount,botIndex) =
    midArgMid(botHistogram, (count+1)/2 - (topCount-topHistogram(topIndex)))
  (topIndex<<16) + botIndex
}

在这里它正在处理一小部分输入数据:

scala> medianFinder(List(1,123,12345,1234567,123456789))
res18: Int = 12345

如果存储了64位整数,则可以在4个遍中使用相同的策略。

2020-07-28