一群朋友去度假,有时互相借钱。
例如,爱丽丝为比尔的午餐支付了 10 美元。后来克里斯给爱丽丝 5 美元搭出租车。我们可以假设每笔交易为一个三元组(X,Y,Z),这意味着第 X 个人借给第 Y 个人 Z 美元。假设 Alice,Bill 和 Chris 是第0,1,2 个人(0,1,2是他们的ID),他们之间的交易可以表示为[ [ 0,1,10 ],[ 2,0,5 ] ]。
给定一组人之间的交易清单,返回结算所需的最低交易数量。
九章算法一篇置顶题目 挺有意思 第一次看到这种需要指数级复杂度的面试题
下面的解法非常具有局限性 如果 debt非零的人多于32 或 64 下面的方法是行不通的
1 public class Solution { 2 3 public int minTransfer(int[][] transactions){ 4 Map<Integer, Integer> debts = new HashMap<Integer, Integer>(); 5 for(int[] t: transactions){ 6 debts.put(t[0], getOrDefault(t[0], 0)-t[2]); 7 debts.put(t[1], getOrDefault(t[1], 0)+t[2]); 8 } 9 int len = 0; 10 int[] account = new int[debts.size()]; 11 for(int total: debts.values()){ 12 if(total!=0){ 13 account[len++] = total; 14 } 15 } 16 if(len ==0) return 0; 17 int dp = new int[1<<len]; 18 Arrays.fill(dp, Integer.MAX_VALUE); 19 for(int l =1; l <dp.length; l++){ 20 int sum =0; 21 int count =0; 22 for(int i=0; i<len;i++){ 23 if((1<<i&l)!=0){ 24 sum + = account[i]; 25 count ++; 26 } 27 } 28 if(sum ==0){ 29 dp[l] = count-1; 30 for(int i =1; i<l;i++){ 31 if((i&l)==i &&(dp[i]+dp[l-i])< dp[l]){ 32 dp[l] = dp[i]+dp[l-i]; 33 } 34 } 35 } 36 } 37 return dp[len-1]; 38 } 39 40 }
时间: 2024-10-10 20:47:57