I have a running stream of integers, how can I take largest k elements from this stream at any point of time.
Create a self-balancing binary search tree and for every new element in the stream, check if the new element is smaller than the current k'th largest element. If yes, then ignore it. If no, then remove the smallest element from the tree and insert a new element. The Kth largest element can be found in O(log K) time.
It can be clearly observed that Kth largest element is the same as (N – K)th smallest element, where N is the size of the given array. Therefore, we can apply the Kth smallest approach to this problem.
Top K Numbers Solution The best data structure to keep track of top K elements is Heap.
Easiest solution would be to populate a min-heap of size k
.
First, populate the heap with the first k
elements.
Next, for each element in the stream - check if it is larger than the heap's head, and if it is - pop the current head, and insert the new element instead.
At any point during the stream - the heap contains the largest k
elements.
This algorithm is O(nlogk)
, where n
is the number of elements encountered so far in the stream.
Another solution, a bit more complex but theoretically better in terms of asymptotic complexity in some cases, is to hold an array of 2k
elements.
First, load the first 2k elements.
Run Selection Algorithm, and find the highest k
out of them. Discard the rest, at this point you have only k
elements left in the array.
Now, fill the array again with the next k
elements, and repeat.
At each point, the array contains the k
largest elements, and up to k
more elements that are not the largest. You can run Selection Algorithm for each query on this array.
Run time analysis:
Maintaining the array: Each selection algorithm is O(2k) = O(k)
. This is done once every k
elements, so n/k
times if n
indicates the number of elements seen so far, which gives us O(n/k * 2k) = O(n)
.
In addition, each query is O(k)
, if the number of queries is Q
, this gives us O(n + Q*k)
run-time.
In order to this solution to be more efficient, we need Q*k < nlogk
Q*k < nlogk
Q < n/k * logk
So, if number of queries is limited as suggested above, this solution could be more efficient in terms of asymptotic complexity.
In practice, getting top k is usually done by using the min-heap solution, at least where I've seen the need of it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With