stream processing
algorithm optimization
data structures
infinite arrays
top-k selection

Optimal algorithm to return largest k elements from an array of infinite number of elements in running stream

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If values arrive as an unbounded stream, you cannot store everything and sort it later. The standard exact solution for tracking the largest k elements seen so far is to keep a min-heap of size k. That gives you O(k) memory usage and O(log k) update cost per incoming item, which is optimal for the usual exact top-k streaming model.

Why a Min-Heap Is the Right Data Structure

The heap stores the current best k elements only. The smallest of those k elements sits at the root, which makes it easy to decide whether a new stream element deserves a place in the top set.

The rule is simple:

  • if the heap has fewer than k elements, push the new value
  • otherwise compare the new value with the heap minimum
  • if the new value is larger, replace the minimum
  • if not, discard it

That way, the heap always contains the largest k values seen so far.

Step-by-Step Logic

Suppose k = 3 and the stream is:

text
5, 1, 9, 2, 8, 10, 3

The heap evolves like this:

  • read 5 -> heap [5]
  • read 1 -> heap [1, 5]
  • read 9 -> heap [1, 5, 9]
  • read 2 -> 2 is larger than heap minimum 1, replace -> heap [2, 5, 9]
  • read 8 -> replace 2 -> heap [5, 8, 9]
  • read 10 -> replace 5 -> heap [8, 9, 10]
  • read 3 -> discard because 3 <= 8

At the end, the heap contains the largest three elements: 8, 9, and 10.

Python Implementation

python
1import heapq
2
3class TopK:
4    def __init__(self, k):
5        self.k = k
6        self.heap = []
7
8    def add(self, value):
9        if len(self.heap) < self.k:
10            heapq.heappush(self.heap, value)
11        elif value > self.heap[0]:
12            heapq.heapreplace(self.heap, value)
13
14    def values(self):
15        return sorted(self.heap, reverse=True)
16
17stream = [5, 1, 9, 2, 8, 10, 3]
18topk = TopK(3)
19
20for x in stream:
21    topk.add(x)
22
23print(topk.values())

This works for a finite stream and also for a conceptually infinite one because memory use never grows beyond k items.

Complexity

For each incoming element:

  • comparison with the minimum is O(1)
  • insertion or replacement in the heap is O(log k)
  • memory remains O(k)

That is much better than storing everything, which is impossible for an infinite stream and wasteful even for very large finite ones.

Why Other Obvious Ideas Are Worse

Keeping a sorted list of the top k elements also works in principle, but updating that list usually costs O(k) time per accepted element. For large k, the heap is better.

Sorting all seen elements is not viable because:

  • the stream may never end
  • memory would grow without bound
  • update cost becomes unnecessary

A max-heap is also the wrong direction because you need fast access to the smallest member of the current top k, not the largest.

Returning Results at Any Time

Because the heap always stores the best k values seen so far, you can query it at any point. If you need the results in descending order, sort the heap copy on demand.

python
print(topk.values())

If you need very frequent readout and k is small, this is usually fine. If k is large and reads are extremely frequent, you may want to think about whether exact sorted output is truly needed at every step.

Variations of the Problem

Be careful about what the question really asks. There are related but different problems:

  • top k largest values overall
  • top k distinct values only
  • top k most frequent values
  • approximate top k in heavy-hitter streams

The min-heap solution here is for the exact largest-value problem, not frequency estimation or distinct-only tracking.

Common Pitfalls

The most common mistake is using a max-heap because the problem mentions largest elements. For this streaming problem, a min-heap of the current top k is the right tool.

Another mistake is storing all values first and sorting later. That defeats the entire point of the streaming constraint.

Developers also sometimes forget to discard values smaller than the heap minimum once the heap is full. That unnecessary work slows the implementation.

Finally, make sure the output requirement is clear. The heap content is correct, but it is not automatically stored in sorted descending order.

Summary

  • The exact streaming top-k solution is a min-heap of size k.
  • Each new value is either inserted, used to replace the minimum, or discarded.
  • Update cost is O(log k) and memory usage is O(k).
  • This works for unbounded streams because it never stores the whole input.
  • Sort the heap only when you need the final or current answer in descending order.

Course illustration
Course illustration

All Rights Reserved.