Compute account balances with rejection and overdraft
Company: Stripe
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Onsite
Quick Answer: This question evaluates stateful transaction processing and aggregation skills, including per-(account,currency) balance maintenance, timestamp-based ordering, rejection rules, and overdraft coverage via a platform account.
Part 1: Final Balances by Account and Currency
Constraints
- 0 <= len(transactions) <= 10^5
- timestamp fits in 64-bit signed integer
- amount fits in 64-bit signed integer
- Each transaction string is well-formed
Examples
Input: (['alice,10,USD,100','bob,12,EUR,40','alice,11,USD,-30','alice,15,EUR,50'],)
Expected Output: ['alice,EUR,50','alice,USD,70','bob,EUR,40']
Explanation: USD and EUR are tracked separately for alice.
Input: (['a,1,USD,10','a,2,USD,-10','b,3,USD,5'],)
Expected Output: ['b,USD,5']
Explanation: Account a ends at 0 USD and is excluded.
Input: ([],)
Expected Output: []
Explanation: Edge case: no transactions means no balances.
Input: (['a,1,USD,-7'],)
Expected Output: ['a,USD,-7']
Explanation: Negative final balances are allowed in Part 1.
Hints
- Use a hash map keyed by (account_id, currency).
- Aggregate first, then filter out zero balances and sort once at the end.
Part 2: Final Balances with Rejected Overdrafts
Constraints
- 0 <= len(transactions) <= 10^5
- timestamp fits in 64-bit signed integer
- amount fits in 64-bit signed integer
- Each transaction string is well-formed
Examples
Input: (['alice,5,USD,-30','alice,1,USD,100','alice,3,USD,-80','bob,2,EUR,20','bob,4,EUR,-25'],)
Expected Output: ['alice,USD,20','bob,EUR,20']
Explanation: After sorting by time, bob's debit and alice's last debit are both rejected.
Input: (['a,2,USD,-5','a,2,USD,10'],)
Expected Output: ['a,USD,10']
Explanation: Same timestamp uses input order, so the debit is seen first and rejected.
Input: (['a,1,USD,10','a,2,USD,-10'],)
Expected Output: []
Explanation: The final balance is exactly 0, so it is omitted.
Input: ([],)
Expected Output: []
Explanation: Edge case: empty input.
Hints
- Sort by timestamp, but keep the original index so ties follow input order.
- Before applying a debit, check whether current_balance + amount would be negative.
Part 3: Final Balances with Platform Shortfall Coverage
Constraints
- 0 <= len(transactions) <= 10^5
- timestamp fits in 64-bit signed integer
- amount fits in 64-bit signed integer
- platform_account_id is a string identifier
- Each transaction string is well-formed
Examples
Input: (['platform,1,USD,100','alice,2,USD,30','alice,3,USD,-50'],'platform')
Expected Output: ['platform,USD,80']
Explanation: Alice uses her 30 first, and the platform covers the remaining 20.
Input: (['platform,1,USD,10','alice,2,USD,5','alice,3,USD,-20'],'platform')
Expected Output: ['alice,USD,5','platform,USD,10']
Explanation: The shortfall is 15, but the platform only has 10 USD, so the debit is rejected.
Input: (['platform,1,EUR,50','alice,2,USD,10','alice,3,USD,-15'],'platform')
Expected Output: ['alice,USD,10','platform,EUR,50']
Explanation: Platform funds must be in the same currency, so EUR cannot cover a USD shortfall.
Input: (['platform,1,USD,10','platform,2,USD,-15','alice,3,USD,2','alice,4,USD,-1'],'platform')
Expected Output: ['alice,USD,1','platform,USD,10']
Explanation: A debit on the platform account itself is rejected if it would make the platform balance negative.
Input: ([],'platform')
Expected Output: []
Explanation: Edge case: no transactions.
Hints
- For an insufficient debit, compute shortfall = debit_amount - account_balance.
- Only change balances after confirming the platform has enough in the same currency.