我有一个流(我不知道它的长度,理论上可能是无穷大)。
我逐个阅读了流的元素。
每次从流中读取元素时,我希望能够返回到目前为止读取的k
最大元素。
(理想情况下,对我来说,它将是python和/或lisp / scheme中的代码)。
K在开头读取,K可以是NUMBER(第3,第4),或者可以是PROCENT(到目前为止读取的元素总数的K%)。如果K = 1/2,那意味着每次提取中值元素...例如,在读取第N个元素后,它必须返回N / 2个最大元素
示例K = 1/2:
3 -> 3
3,4 -> 3
3,4,2 -> 3
3,4,2,1 -> 2
etc.
我认为这个例子足以澄清这个问题。我需要最少的时间来提取Kth元素。 (这假设在O(1)中读取流,然后插入读取值,然后提取Kth元素)。
我希望任何解决方案都优于O(n)。
答案 0 :(得分:1)
我会使用包含第k个最大元素的堆(或者在百分比情况下包含所有元素的二叉搜索树)。 如果百分比,这给你O(Log(k))(或O(Log(n))。
案例kth:
案例百分比: 在二叉搜索树中插入新元素,在这样的树中,可以很容易地找到第k个元素。
答案 1 :(得分:1)
因此,由于你需要第k个元素并且k在运行算法之前是已知的,所以首先观察你需要存储最多k个元素,k个最小元素。 当您阅读新元素时,您需要在某些数据结构中插入元素,以保持其属性并有机会快速检索答案。 1)您可以使用最多具有k个元素的max-heap。读取元素插入堆(log(k)),然后如果你有更多k元素(k + 1要精确)你需要extract_max O(log(k))来提取和重建,答案将在堆顶部访问O(1)。 因此,每次使用log(k)获取第k个元素时,总共需要所有元素 - n * log(k)。
2)在使用百分比的情况下,元素的位置将根据处理的元素数量动态计算,在这里您可以使用订单统计树,http://en.wikipedia.org/wiki/Order_statistic_tree具有相同的日志(元素数量)插入和log(元素数量)查找。
答案 2 :(得分:0)
如果保留到目前为止看到的 k 最大元素的排序列表,您始终可以返回列表中的最小元素。插入列表是 O(k),最小的是 O(1)。由于列表的大小不依赖于 n ,因此它在 n 方面是不变的。
编辑2:正如我在下面的评论中所说,我认为跳过列表可能是列表的最佳选择。如果我没记错的话,它有 O(log k)时间插入, O(1)时间用于删除最小元素, O(k log k) )空间(对于链表的 O(k))。
答案 3 :(得分:0)
堆很不错。 O(1)查找最小值,O(logn)删除。
对于这类问题,Treaps的平均速度非常快(很好)。它们允许在O(logn)时间内访问(或删除)最小值或最大值。 http://stromberg.dnsalias.org/~strombrg/treap/ 那里有一个“巢”模块(n最好)就是为了这种事情。
红黑树的速度并不快,但它们可以提供相当平稳的分布式性能成本,因此您不会像快照一样快速 - 快速 - 快速 - 慢 - 快 - 快 - 快 - 慢。相反,它更像是中度 - 中度 - 中度 - 中等。
在这里尝试“手指树”可能会很有趣。手指树据称可以在树中进行O(1)查找最小值和最大值的查找。我不确定删除。