SWE · Coding / Onsite summary

Airbnb Refund 分配:支付方式优先、较新支付与剩余可退额

Refund 面经给 CREDIT→CREDIT_CARD→PAYPAL 与同方式按较新支付;核已有退款后分配,明确题目样例互相矛盾。

题目重点:Refund 面经给 CREDIT→CREDIT_CARD→PAYPAL 与同方式按较新支付;核已有退款后分配,明确题目样例互相矛盾。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 每笔 payment 有 ID、方式、时间、原额和已有 refund 总额;当前可退额=max(0,paid−previousRefunded),不超过原支付额。
  • 先按方式优先级,再按支付时间降序;同时间用稳定 ID/原输入序 tie-break,题目未定义。
  • 若请求退款额大于所有剩余可退额,训练版返回不足额错误而不部分提交;题目未明确超额处理。
  • 金额用整数最小单位,避免浮点误差;退款输出可拆为多笔 payment-linked 项。

解题路线

  1. 先汇总所有已有 refund,按 paymentId 校验不会超过 paid,并算 remaining;若总 remaining<目标,先拒绝且不修改状态。
  2. 把 remaining>0 的 payment 按 (方式序号,−timestamp,稳定ID) 排序,依序分配 min(目标剩余,该笔 remaining),只有一笔支付无法覆盖剩余请求时才进入下一笔。
  3. 事务性写入退款明细,使用 requestId 幂等;若支付网关异步返回,保留 PENDING/UNKNOWN 并对账,不能超时就重新生成新退款。
  4. 用题目矛盾样例做算术检查:例 1 请求 50,CREDIT 40 与 PAYPAL 60,按列出的优先级应分 40+10,而非只退 30。

手动走一遍

例 2:Payment1 CREDIT 40,已有退款 20,故只剩 20;Payment2 PAYPAL 60 日期较早,Payment3 PAYPAL 40 日期较新。再退 50 时先 Payment1 退 20,再按同方式较新优先给 Payment3 退 30。题目初列 40+10 的输出忽略了已有退款。

规模与取舍

P 笔支付、R 条已有退款,聚合 O(P+R),排序 O(P log P),分配 O(P),额外空间 O(P);若交易不断新增,可按方式/时间维护索引。

易错点与追问

容易失分的边界

  • 忽略之前已退金额,导致 payment 超额退款。
  • 先按时间而非支付方式排序。
  • 分配给下一笔前没有尽可能用满当前笔。
  • 把冲突样例的一行输出当精确题意。
  • 用浮点金额。

继续深挖

  • 若部分退款在网关处理中,remaining 如何锁定?
  • 退款请求重复提交怎样幂等?
  • 同方式同时间如何稳定排序?
  • 超额请求是否允许部分成功?
✓已复制微信号!