cswork / libraryOpen practice workspace

Coding questions · Meta

Maintain top N payers

This interview question evaluates algorithm design, data structures, correctness, complexity, edge cases, and implementation details in a realistic interview setting. A strong answer for Maintain top N payers states assumptions, handles edge cases, explains trade-offs, and shows how to validate the result clearly.

Implement topNPayers(n) that returns the n accounts with the highest cumulative outgoing payment amounts as strings formatted "{accountId}:{totalOutgoing}". Rank by the sum of amounts from debit operations (e.g., pay, executed scheduled payments). Support online updates as new debits occur. Explain your data structures (e.g., a size-N min-heap or an ordered map), tie-breaking rules, how to handle accounts with equal totals, and the time/space complexity per update and query.

What a Strong Answer Covers

  • A clear algorithm with the right data structures and enough pseudocode or code-level detail to implement it.
  • A correctness argument that explains why the algorithm covers all required cases.
  • Time and space complexity, plus at least one alternative approach when relevant.
  • Focused tests for normal cases, edge cases, and failure modes.

Follow-up Questions

  • How would the approach change if the input were streaming or too large for memory?
  • What invariants would you assert in production code?
  • Which tests would catch off-by-one, duplicate, or tie-breaking bugs?

Maintain Top N Payers

You are building the reporting layer of a bank system. Each debit operation (a pay or an executed scheduled payment) records an outgoing amount from an account. Implement topNPayers(payments, n) that returns the n accounts with the highest cumulative outgoing amounts.

Each element of payments is a pair [accountId, amount] describing one debit (the same account may appear many times). Return a list of strings formatted as "{accountId}:{totalOutgoing}", ordered by total outgoing amount descending. When two accounts have the same total, the account with the lexicographically smaller accountId comes first.

If n is larger than the number of distinct accounts, return all of them. If n is 0 or there are no payments, return an empty list.

Example: payments = [["a",100],["b",50],["a",25],["c",75]], n = 2 -> ["a:125", "c:75"] (a totals 125, c totals 75, b totals 50).

Note on data structures: an interviewer expects you to discuss maintaining totals in a hash map and answering the query with either a full sort (O(A log A) per query) or a size-N min-heap (O(A log N)); for online updates a heap or ordered map keyed by total keeps each update near O(log N).

Constraints

  • 0 <= len(payments) <= 10^5
  • 0 <= n <= number of distinct accounts (n may exceed it; return all)
  • amount is a non-negative integer
  • accountId is a non-empty string
  • Ties are broken by lexicographically smaller accountId

Hints

  1. Aggregate first: walk the payments once and accumulate each account's total in a hash map. The same account can appear in many debits.
  2. To rank, sort the map entries by total descending; for equal totals fall back to ascending accountId so the order is deterministic.
  3. For an online / streaming version, maintain a size-N min-heap (or an ordered map keyed by total) so each update is O(log N) instead of re-sorting everything.
  4. Watch the edge cases: n = 0 and empty payments both return an empty list, and n larger than the distinct-account count returns every account.

Solution

Solution Alignment

The prompt asks for an implementation-level answer. The safest way to present it is to define the state, maintain clear invariants, then walk through complexity and tests.

Problem Restatement

Implement topNPayers(n) that returns the n accounts with the highest cumulative outgoing payment amounts as strings formatted "{accountId}:{totalOutgoing}". Rank by the sum of amounts from debit operations (e.g., pay, executed scheduled payments). Support online updates as new debits occur. Explain your data structures (e.g., a size-N min-heap or an ordered map), tie-breaking rules, how to handle accounts with equal totals, and the time/space complexity per update and query.

Recommended Approach

When repeatedly combining the two smallest available values, use a min-heap. Pop the two smallest, add their sum to the total cost, and push the combined value back until one value remains. This is the same greedy structure as Huffman merging.

Correctness

The implementation should maintain an invariant after each loop or operation that directly matches the problem statement. At termination, that invariant implies the returned value has considered every valid candidate exactly once, or has preserved the required data-structure state after every API call.

Complexity

Time: O(n log n). Space: O(n).

Edge Cases and Tests

No values, one value, duplicate values, very large sums, and proving the greedy choice by exchange argument.