题目重点:先以净额守恒构造合法转账,再把最少笔数作为独立优化追问,最后设计可审计的 dry-run 与账务对照。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 所有余额用同一币种的整数最小单位;各账户 current 和 target 的总和相等,否则只有内部转账不可能完成。
- 训练版账户可在结算过程中临时收/付但不能透支;若题面允许负余额或外部资金账户,解法约束会变。
- 任意方案与最少笔数是两段:前者只需正确且总额守恒,后者不能仅凭一轮贪心保证最优。
解题路线
- 算 delta_i=target_i−current_i,delta>0 是应收,delta<0 是应付;去掉零额,核对所有 delta 之和为 0。
- 任意方案:维护应付/应收两个队列,每次在一对账户间转 min(应付剩余,应收剩余),更新剩余;每次至少清掉一个非零节点,所以至多 P+Q−1 笔。若不允许中间透支,从有足够余额的付款人开始并检查约束。
- 最少笔数:对非零 net 数组做回溯。找首个未清偿者 i,与符号相反的 j 合并,把 net[i] 加到 net[j],递归剩余;相同净额的 j 跳过对称分支,恰好抵消时可优先尝试。记录配对方向/金额以重建转账。最坏指数级,不能把任意方案的 P+Q−1 当最优证明。
- 审计用不可变交易 ID、源/目标、金额、幂等键与批次版本做 dry run;提交时用数据库事务/锁保证一笔转账借贷两边原子。事后比较 expected target、实际 ledger 聚合与 balance 视图,并对缺/重 ID 给异常清单,而不是只比较总和。
手动走一遍
训练例 current={A:0,B:10,C:10},target={A:10,B:5,C:5},delta={A:+10,B:−5,C:−5},B→A 5、C→A 5 完成。另例净额 [+5,+5,−5,−5] 有两笔完美抵消;错误的任意配对也可能产生三笔,说明最少笔数需要搜组合。
规模与取舍
n 个账户求净额 O(n),任意结算 O(n) 时间/空间;最少笔数回溯最坏指数级,可按零净额剔除、对称剪枝及小规模动态规划优化。审计扫描 T 笔 ledger O(T) 并需对批次 ID 做去重。
易错点与追问
容易失分的边界
- 不检查目标总额=当前总额就开始转账。
- 把一种贪心可行方案误称最少笔数。
- 只对账总和相同,漏掉错账户、重复记账或单边入账。
- 金额用 float,精确清偿时出现残留分。
- 把 q9 的逐笔负余额拒绝/平台代垫与此题的目标结算混为一题。
继续深挖
- 若账户上百且最少交易 NP 型回溯不现实,如何给可解释的近似方案?
- 若账户分多币种,汇率与费用会破坏什么守恒条件?
- dry run 后到提交前余额改变,如何用版本/事务防止计划过期?
