You are given an array of transactions transactions
where transactions[i] = [fromi, toi, amounti]
indicates that the person with ID fromi
gave amounti $
to the person with ID toi
.
Return the minimum number of transactions required to settle the debt between a set of people.
Note:
0
, it means that some transactions have been overlooked. In that case, output -1
.Example 1:
Input: transactions = [[0,1,10],[2,0,5]] Output: 2 Explanation: PersonId 0 gave personId 1, 10$. PersonId 2 gave personId 0, 5$. Two transactions are needed. One person needs to give another one 5$ and a second person needs to give the first one 5$.
Example 2:
Input: transactions = [[0,1,10],[1,0,1],[1,2,5],[2,0,5]] Output: 1 Explanation: PersonId 0 gave personId 1, 10$. PersonId 1 gave personId 0, 1$. PersonId 1 gave personId 2, 5$. PersonId 2 gave personId 0, 5$. Therefore, person 1 only need to give person 0 9$. So only one transaction is needed.
Constraints:
1 <= transactions.length <= 8
transactions[i].length == 3
0 <= fromi, toi < 20
fromi != toi
1 <= amounti <= 100
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The goal is to make sure everyone's debts are settled using the fewest number of transactions possible. The brute force approach to solving this problem involves trying every single possible combination of transactions to see which one uses the least number of transactions overall.
Here's how the algorithm would work step-by-step:
def min_transactions_brute_force(transactions):
net_balances = {}
for transaction in transactions:
debtor = transaction[0]
creditor = transaction[1]
amount = transaction[2]
net_balances[debtor] = net_balances.get(debtor, 0) - amount
net_balances[creditor] = net_balances.get(creditor, 0) + amount
balances = list(net_balances.values())
def settle_debts(balances, transaction_count):
if not balances:
return transaction_count
for i in range(len(balances)):
if balances[i] == 0:
continue
temp_balances = balances[:]
# Iterate through the remaining non-zero balances
for j in range(i + 1, len(balances)):
if balances[j] == 0:
continue
temp_balances = balances[:]
temp_balances[i] -= balances[j]
temp_balances[j] = 0
# This is a core decision point.
# Recursively try all the settlement combinations.
min_count = settle_debts(temp_balances, transaction_count + 1)
return min_count
return float('inf')
# Start the recursive process
# by initiating transaction_count to zero
minimum_transaction_count = settle_debts(balances, 0)
if minimum_transaction_count == float('inf'):
return 0 # All balances must have been zero
return minimum_transaction_count
The most efficient way to solve this problem is to simplify it by focusing on what each person ultimately owes or is owed. We can then iteratively settle these debts by pairing up creditors and debtors to cancel out as much debt as possible in each transaction. By strategically pairing people, we minimize the total number of transactions needed.
Here's how the algorithm would work step-by-step:
def min_transactions(transactions):
person_balances = {}
for transaction in transactions:
payer = transaction[0]
receiver = transaction[1]
amount = transaction[2]
person_balances[payer] = person_balances.get(payer, 0) - amount
person_balances[receiver] = person_balances.get(receiver, 0) + amount
balances = list(person_balances.values())
balances = [balance for balance in balances if balance != 0]
def settle_debts(balances):
number_of_transactions = 0
while balances:
# Find the max credit and max debit to settle
max_credit = max(balances)
max_debit = min(balances)
amount_to_settle = min(abs(max_debit), max_credit)
# Settle as much as possible
balances.remove(max_credit)
balances.remove(max_debit)
if max_credit - amount_to_settle != 0:
balances.append(max_credit - amount_to_settle)
if max_debit + amount_to_settle != 0:
balances.append(max_debit + amount_to_settle)
number_of_transactions += 1
return number_of_transactions
# Balances represents all net debts and credits.
return settle_debts(balances)
Case | How to Handle |
---|---|
Null or empty transaction list | Return 0 if the transaction list is null or empty, as there are no debts to settle. |
Transaction list with a single transaction | Return 1 as a single transaction is already the minimum required to settle that single debt. |
All transactions result in a net balance of zero for all individuals. | Return 0 since all accounts are already balanced and no transactions are needed. |
Large transaction amounts leading to potential integer overflow when calculating balances. | Use a data type that can accommodate large numbers, such as long, to prevent integer overflow. |
Transactions forming a cycle (e.g., A owes B, B owes C, C owes A) | The balance calculation and zeroing-out approach correctly handles cycles by iteratively reducing debts. |
A single person owes multiple people, or multiple people owe a single person. | The balance calculation correctly aggregates debts to and from each person. |
Transactions with identical (from, to) pairs but different amounts (representing multiple debts between the same two people). | The balance calculation correctly aggregates the amounts for duplicate (from, to) pairs, treating them as a single consolidated debt. |
Large number of people and transactions leading to memory constraints. | The memory usage should scale linearly with the number of people, which should generally be manageable for reasonable problem sizes. |