Compute minimal transfers to settle group expenses
Company: Google
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates the ability to compute per-person net balances and optimize peer-to-peer payments to minimize the total number of transactions, exercising algorithmic reasoning, numeric bookkeeping under equal-split constraints, and efficiency for larger inputs.
Constraints
- amount is divisible by len(payees), so each share is an exact integer (cents).
- Names are case-sensitive strings.
- The payer may also appear in payees (they consume a share too).
- Each output transfer's payees list contains exactly one creditor.
- Net balances always sum to 0, so a full settlement always exists.
Examples
Input: ([{'payer': 'alice', 'amount': 4000, 'payees': ['bob', 'jess', 'alice', 'sam']}, {'payer': 'jess', 'amount': 2000, 'payees': ['jess', 'alice']}],)
Expected Output: [{'payer': 'bob', 'amount': 1000, 'payees': ['alice']}, {'payer': 'sam', 'amount': 1000, 'payees': ['alice']}]
Explanation: alice paid 4000 split 4 ways (1000 each): alice net = 4000 - 1000 = +3000 before the second expense. jess paid 2000 split 2 ways (1000 each): jess net = -1000 (exp1) + 2000 - 1000 (exp2 own share) = 0; alice loses another 1000 -> +2000. bob and sam each owe 1000. Greedy by sorted name: bob -> alice 1000, sam -> alice 1000.
Input: ([],)
Expected Output: []
Explanation: No expenses means no balances and no transfers.
Input: ([{'payer': 'a', 'amount': 1000, 'payees': ['b']}],)
Expected Output: [{'payer': 'b', 'amount': 1000, 'payees': ['a']}]
Explanation: a paid 1000 entirely for b, so b owes a 1000. A single transfer b -> a settles it.
Input: ([{'payer': 'a', 'amount': 1000, 'payees': ['a']}],)
Expected Output: []
Explanation: a paid 1000 for only themselves, so a's net balance is 0. No one owes anyone; no transfers.
Input: ([{'payer': 'a', 'amount': 3000, 'payees': ['a', 'b', 'c']}, {'payer': 'b', 'amount': 3000, 'payees': ['a', 'b', 'c']}],)
Expected Output: [{'payer': 'c', 'amount': 1000, 'payees': ['a']}, {'payer': 'c', 'amount': 1000, 'payees': ['b']}]
Explanation: Each expense splits 3000 into 1000 shares. a: +3000 -1000 -1000 = +1000. b: -1000 +3000 -1000 = +1000. c: -1000 -1000 = -2000. c owes 2000 total; greedy pays c -> a 1000 then c -> b 1000 (two transfers, the minimum).
Input: ([{'payer': 'x', 'amount': 6000, 'payees': ['x', 'y', 'z']}],)
Expected Output: [{'payer': 'y', 'amount': 2000, 'payees': ['x']}, {'payer': 'z', 'amount': 2000, 'payees': ['x']}]
Explanation: x paid 6000 split 3 ways (2000 each). x net = 6000 - 2000 = +4000; y and z each owe 2000. y -> x 2000, z -> x 2000.
Hints
- First reduce every expense to a single net balance per person (in cents): a payer gains the full amount, and every payee loses amount / len(payees).
- People with a positive balance are creditors (owed money); people with a negative balance are debtors (owe money). People with zero balance need no transfer.
- Sort debtors and creditors lexicographically by name to make the result deterministic, then greedily transfer min(remaining_debt, remaining_credit) between the current debtor and creditor, advancing whichever side reaches zero.