如何从数组中找到第100个最大数字

时间:2014-04-12 10:54:07

标签: php data-structures time-complexity

当数组扩展并且每秒或不到一秒钟填充或添加数据时,我必须从数组中找到第90-100个最大数字。可以视为运行数据流。我想过使用数据结构二叉树,但是每次构建树并将新数据放在适当的位置都会非常繁琐,因为数据的速度非常快。

我想知道哪种数据结构最适合查找第90-100个最大数据。

1 个答案:

答案 0 :(得分:3)

一种解决方案是使用大小为100的Min heap。当每个项目都进来时,将它与堆中的最小项目进行比较。如果它大于堆中的最小项,则删除最小的项并将其替换为新项。无论何时你想要第100个最大的项目,你只需从堆中获得最小项目。

在伪代码中,它看起来像这样:

heap = new MinMaxHeap()
while (item available)
{
    if (heap.count < 100)
    {
        add item to heap
    }
    else if (item > heap.PeekMin())
    {
        remove minimum item from heap
        add item to heap
    }
}

任何时候你想要第100个最大的项目,只需在堆上做PeekMin

检查最小项目(即PeekMin)是O(1)操作。删除和插入都是O(log k),其中k是堆上的项目数。在实践中,假设项目以随机顺序呈现,您只需要删除并替换大约10%的项目。最坏的情况是,当项目按升序显示时,您必须删除/替换每个项目。

现在,如果你想要第90到第100项,你需要对堆进行排序并获取前11项。幸运的是,排序数组是一个有效的二进制堆,因此排序不会破坏堆属性。你只需要分拣100件物品,所以它会非常快。

将一个简单的二进制堆实现为一个数组非常容易。我在一系列博客文章中详细描述了它,从Priority Queues开始。代码示例在C#中,但您可以轻松地将它们转换为php。

另一种方法是使用两个堆。第一个堆如上所述:前100个项目。第二个堆将是一个Max堆,您可以在其中存储前100个中最小的11个项。第二个堆上的替换策略是相反的。也就是说,您将新项目与堆根部的项目进行比较,并替换新项目更小。使用这种结构,如果你想按顺序排列项目,你仍然需要排序第二个堆,但是排序11个项目真的快。