JavaScript找零函数优化求助:基于$2、$5、$10纸币的最优实现
最优找零方案:$2、$5、$10面额的贪心解法
嘿,刚学JS碰到这种问题太正常了!我当初入门的时候也在类似的贪心问题上踩过坑,不过咱们这个面额组合刚好完美适配贪心算法——毕竟不是所有面额都能用贪心,但$2、$5、$10这组的特性决定了「优先用大面额」就是最优解,给你一步步拆解:
核心思路:贪心选择的合理性
因为$10是最大面额,每张抵10块,能最快减少找零金额;其次是$5,最后是$2。不过要注意一个特殊情况:奇数金额必须用至少一张$5(毕竟只有$5是奇数,$2和$10都是偶数,奇数=奇数+偶数,所以先拿一张$5,剩下的就变成偶数,就能用$2和$10凑了)。
具体步骤
- 合法性校验:
- 找零金额小于$2?直接返回无法找零(最小面额是$2)
- 如果是奇数金额且小于$5?也没法找零(比如$3,凑不出来)
- 处理奇数金额:如果金额是奇数,先减去$5,张数+1,剩下的金额变成偶数
- 优先用$10:计算能拿多少张$10,张数加上这个数量,剩下的金额减去对应总额
- 用$2凑剩余:剩下的偶数金额直接除以2,得到$2的张数,加到总张数里
JavaScript代码实现
function calculateMinChange(amount) { // 先判断基础合法性 if (amount < 2) { return "无法完成找零(金额过小)"; } let totalNotes = 0; let remaining = amount; // 处理奇数金额的特殊情况 if (remaining % 2 !== 0) { if (remaining < 5) { return "无法完成找零(无法用现有面额组合)"; } remaining -= 5; totalNotes += 1; } // 优先使用最大面额$10 const tenCount = Math.floor(remaining / 10); totalNotes += tenCount; remaining -= tenCount * 10; // 剩余偶数金额用$2凑 const twoCount = remaining / 2; totalNotes += twoCount; return `最少需要${totalNotes}张纸币`; }
测试用例验证
- 输入
10→ 返回「最少需要1张纸币」(1张$10) - 输入
15→ 返回「最少需要2张纸币」(1张$10 + 1张$5) - 输入
7→ 返回「最少需要2张纸币」(1张$5 + 1张$2) - 输入
8→ 返回「最少需要4张纸币」(4张$2,没有更优的组合) - 输入
3→ 返回「无法完成找零(无法用现有面额组合)」
为什么这个解法是最优的?因为对于这个面额组合,贪心选择不会出现「为了省一张大面额,导致后续需要更多小面额」的情况。比如找$14,贪心用$10+$2+$2(3张),如果硬要用$5+$5+$2+$2(4张)反而更多,所以贪心完全可行。
内容的提问来源于stack exchange,提问作者Platiplus




