leetcode
leetcode 401 ~ 450
最优账单平衡

最优账单平衡

难度:

标签:

题目描述

代码结果

运行时间: 40 ms, 内存: 0.0 MB


/*
 * 思路:
 * 1. 首先计算每个帐户的净余额。
 * 2. 将余额非零的账户存入列表。
 * 3. 使用递归和Stream API来计算最少的交易次数以平衡账户。
 */
import java.util.*;
import java.util.stream.*;
 
public class Solution {
    public int minTransfers(int[][] transactions) {
        Map<Integer, Long> map = Arrays.stream(transactions).flatMapToInt(Arrays::stream)
            .collect(HashMap::new, (m, t) -> {
                m.put(t[0], m.getOrDefault(t[0], 0L) - t[2]);
                m.put(t[1], m.getOrDefault(t[1], 0L) + t[2]);
            }, HashMap::putAll);
        List<Long> debt = map.values().stream().filter(amount -> amount != 0).collect(Collectors.toList());
        return dfs(0, debt);
    }
    private int dfs(int start, List<Long> debt) {
        while (start < debt.size() && debt.get(start) == 0) start++;
        if (start == debt.size()) return 0;
        int result = Integer.MAX_VALUE;
        for (int i = start + 1; i < debt.size(); i++) {
            if (debt.get(i) * debt.get(start) < 0) {
                debt.set(i, debt.get(i) + debt.get(start));
                result = Math.min(result, 1 + dfs(start + 1, debt));
                debt.set(i, debt.get(i) - debt.get(start));
            }
        }
        return result;
    }
}

解释

方法:

这个题解通过将每一个人的债务和债权计算出来,然后通过深度优先搜索(DFS)来找到最小的交易次数来平衡所有的账户。首先,通过遍历所有的交易来计算每个人的最终的债务或债权。接下来把这些债务/债权值存储在一个数组中,然后使用递归的DFS来尝试所有的可能的交易组合,以找到可以使所有账户平衡的最小交易次数。在DFS中,我们跳过余额为0的账户,并尝试将当前账户的债务/债权通过交易转移给其他账户。如果当前的交易次数已经超过了之前找到的最佳解,那么就提前终止这条路径的探索。

时间复杂度:

O(n!)

空间复杂度:

O(n)

代码细节讲解

🦆
在DFS过程中,提前终止探索的条件`cnt >= res`是如何确定的?这里的`res`和`cnt`具体代表什么含义?
`res`代表目前为止找到的最小交易次数,而`cnt`代表当前DFS路径上的交易次数。如果`cnt`已经等于或超过`res`,则继续当前路径的探索不会得到更优解,因此可以提前终止,以节省计算资源并提高算法效率。
🦆
为什么在处理债务和债权时选择使用`defaultdict(int)`而不是普通的字典?这种选择对算法的性能有什么影响?
使用`defaultdict(int)`可以自动为未初始化的键提供默认的整数值0,这在处理债务或债权时简化了代码,因为不需要检查和初始化键值。这种方法提高了代码的清晰度和执行效率,因为少了很多条件判断和键初始化的步骤。
🦆
DFS函数中,为什么在处理完一个账户后要尝试将其债务或债权完全转移给另一账户,而不是部分转移?这样的全额转移对算法效率有何影响?
尝试将债务或债权完全转移是为了简化问题的复杂度和决策过程。部分转移会导致状态空间显著增加,因为每次转移都有多种选择,这会使得DFS探索的路径和时间复杂度大幅增加。全额转移使得每个决策点的选择减少,从而可以更快地找到最小交易次数的解决方案。

相关问题