擅长:python、mysql、java
<p>假设您在一个单独的列表中有<code>k</code>事物的内存。然后,以下内容将像<code>O((n + n^2/k) log(k))</code>一样缩放。在<code>k</code>常数的极端情况下,它是二次的,如果<code>k</code>是<code>n</code>的固定分数,那么它是<code>O(n log(n))</code></p>
<p>其思想是为尚未返回的<code>k</code>最小的东西创建一个缓冲区。将它转换为一个最小堆,然后使用堆操作在每个返回的元素<code>O(log(k))</code>的时间内从中返回内容。当缓冲区为空时,重新填充缓冲区,然后再次像以前一样继续操作。(缓冲区开始为空。)</p>
<p>要创建缓冲区,请扫描数组,放入比上次返回的值大的值,直到到达缓冲区中的<code>k</code>个值为止。然后将它转换为一个最大堆,当堆中的内容大于返回的内容,小于已经存在的内容时,替换堆中的内容。重新填充后,将其重新组织为最小堆</p>
<p>您需要重新填充缓冲区<code>n/k</code>次。每次都是<code>O(n log(k))</code>操作的最坏情况。(如果<code>k << n</code>且数组是随机顺序的,则平均运行时间为<code>O(n)</code>,因为几乎所有内容都与堆中的最大值进行比较,然后丢弃。)</p>
<p><em>重要的边缘情况:</em>如果您有重复的,您需要考虑这样一种情况,即您的缓冲区只包含最大事物的一些副本。一种方法是跟踪堆中应该有多少个最大对象的副本,但实际上没有存储在那里。这样,在清空堆之后,也可以返回所有丢失的副本,然后继续扫描较大的元素</p>