call(back)
Algorithms & Data StructuresmediumSign in to star problems

Memory-Bounded Ranked Ballot Counter

Millions of ranked ballots have to be counted without ever holding them all in memory: votes are read in batches, and memory must stay proportional to the number of candidates.

A ballot is a list of candidate names, most preferred first. Score it Borda-style: a ballot of n names gives n - 1 points to its first name, n - 2 to the second, and so on down to 0 for the last. Implement RankedBallotCounter(batchSize):

  • add(ballot) — buffer the ballot; as soon as the buffer holds batchSize ballots, flush it into the running totals and empty it. Never keep every ballot.
  • extend(ballots) — add each one.
  • results(topK?) — flush whatever is buffered, then return [[candidate, score], ...] sorted by score descending, then name ascending; topK truncates when given.
  • firstPlaceCounts() — flush, then return [[candidate, ballotsRankingThemFirst], ...] with the same ordering.
  • stats() — { ballotsSeen, batchesFlushed, buffered } without flushing: ballots counted so far by flushes, the number of non-empty flushes, and how many ballots are still buffered.

Every candidate that appears on any ballot appears in results(), even with a score of 0. An empty ballot is a ballot: it counts toward ballotsSeen and scores nobody.

counter = RankedBallotCounter(10)
counter.add(["alice", "bob", "carol"])   // alice 2, bob 1, carol 0
counter.add(["bob", "alice", "carol"])   // bob 2, alice 1
counter.add(["alice", "carol", "bob"])   // alice 2, carol 1
counter.results()  ->  [["alice", 5], ["bob", 3], ["carol", 1]]

Hints

Hint 1

The score is a sum over ballots, so the state you need is one counter per candidate — O(candidates), independent of how many ballots arrive. The buffer exists only to model batch processing; flushing it means folding each buffered ballot into the counters and clearing it.

Hint 2

Sort the results with a compound key: score descending, then name ascending. Deterministic tie-breaks matter more in an evaluation harness than anywhere else, because a flaky ranking looks like a regression.

Asked at