Skip to content
Reliable Data Engineering
Practice problem hard samplingstreamingprobability
Solve it in the browser (Python editor)

Uniform Sample from a Stream of Unknown Length

Difficulty: Hard · Topics: sampling, streaming, probability · Asked at: Google, Meta, LinkedIn, Netflix

Problem

Implement reservoir_sample(stream, k, rng) returning a list of k items chosen uniformly at random from an iterable of unknown length (all items if fewer than k), using O(k) memory. Use rng.randint(a, b) (inclusive) for randomness so results are reproducible with a seeded random.Random.

Starter code

import random

def reservoir_sample(stream, k: int, rng: random.Random) -> list:
    pass

Hints

Hint 1

Fill the reservoir with the first k items.

Hint 2

For item i (0-based, i ≥ k), pick j = randint(0, i); if j < k replace reservoir[j].

Solution

import random

def reservoir_sample(stream, k: int, rng: random.Random) -> list:
    reservoir = []
    for i, item in enumerate(stream):
        if i < k:
            reservoir.append(item)
        else:
            j = rng.randint(0, i)
            if j < k:
                reservoir[j] = item
    return reservoir

Tests

Your solution should pass these:

import random
from collections import Counter
assert reservoir_sample(range(3), 5, random.Random(1)) == [0, 1, 2]
s = reservoir_sample(range(1000), 10, random.Random(42))
assert len(s) == 10 and len(set(s)) == 10 and all(0 <= x < 1000 for x in s)
# uniformity check: each of 10 items should be picked ~ 3/10 of the time
rng = random.Random(0)
counts = Counter(x for _ in range(20000) for x in reservoir_sample(range(10), 3, rng))
assert all(abs(c / 20000 - 0.3) < 0.02 for c in counts.values()), counts

Explanation

Why it’s uniform: item i is kept with probability k/(i+1) when it arrives; it then survives each later arrival j with probability 1 − 1/(j+1), and the product telescopes to exactly k/n for every item. O(n) time, O(k) memory, one pass. Uses: sampling records for data profiling, debugging, ML training subsets from unbounded logs. Distributed version: sample per partition with random keys and keep the global top-k smallest keys (weighted variants exist).