题目重点:明确百分比、固定减免、买赠的资格和叠加合同,用结构化调整项计算金额并解释来源中的买赠歧义。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练合同购物车已经包含赠品,买x赠y表示同SKU每完整x+y件有y件免单;自动加赠品版本另讨论,不能混用。
- 金额用整数最小货币单位;单币种、无税运费。百分比按明确舍入规则到分,题目未明确具体规则,训练用向下取整。
- 折扣按明确priority顺序施加到剩余应付金额;固定减免封顶剩余金额,资格条件独立于计算,题目并未给叠加政策。
解题路线
- 先讲执行管线:validate cart→算各行原价→筛选eligible规则→按叠加策略规划→逐条生成adjustment→校验守恒与非负→返回明细。抽象类只是该流程的工具,先回答钱在哪里扣。
- Discount拥有isEligible(context,line)、quote/apply(context,line,current)返回结构化调整:规则id、适用数量、减免额、基数、解释。Engine编排与汇总,规则不自行修改全局cart,方便dry run和测试。
- 百分比折扣明确premium资格与基数:原价或剩余价不能两边混用。固定减免区分每单/每行/每件;每单减免按确定顺序或比例分摊,保留舍入余数处理,避免同折扣重复扣每行。
- 买赠按训练合同free_qty=floor(qty/(x+y))·y,减免free_qty·unit_price;若先百分比再买赠,应定义赠品免费价值按原价还是已折价,并用数量/金额调整避免同件重复免单。
- 多个互斥规则分组,Engine按政策挑选;‘选择最优惠组合’可能是组合优化,不能用任意顺序贪心假称全局最优。生产返回price_quote_id、规则版本及到期时间,支付时重新验证或锁定报价。
- 金额验证为final=base−sum(adjustments)、每行非负、总分摊等于订单折扣。退款按已结算行分摊及赠品政策处理,不能直接用当前规则重算旧订单。
手动走一遍
训练例单价1000分、数量3、BUY_2_GET_1:原价3000、免1件1000、剩2000。若随后premium九折,再减200、最终1800。若规则要求先九折,买赠计算基数也须明确,不能先减300又按原价免1000导致1700而不解释政策。
规模与取舍
L行与D规则朴素O(LD),资格索引可减少候选。互斥选择若每组独立可线性比较;跨商品额度/组合规则可能需要DP或搜索,不能承诺一律O(LD)。
易错点与追问
容易失分的边界
- 把来源的自动赠品与cart内赠品语义混为一谈。
- float金额导致分摊误差。
- 只创建类却没有调用isEligible/apply的主流程。
- 每行各扣一次订单级固定折扣。
- 折扣顺序隐含、总减免超过原价。
继续深挖
- 买x赠y跨SKU且赠最便宜商品,规则如何变化?
- 订单满减在退款时如何分摊?
- 同一购物车如何返回最优惠组合且说明计算时间?
- 规则热更新后旧报价还能支付吗?
