You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LeetCode最小硬币找零一维数组自上而下DP实现问题排查求助

硬币找零问题代码错误排查

核心错误原因

你的代码本质问题是记忆化缓存的定义和递归逻辑不匹配,破坏了动态规划子问题的独立性:

  • 你定义的dp[sum]本意是存储凑出金额sum需要的最少硬币数,是和当前路径已使用硬币数无关的全局最优解
  • 但你在递归函数中传入了路径相关的curCoins参数,第一次计算dp[sum]时会把当前路径的结果存进去,而这个结果大概率不是全局最优,后续所有访问到dp[sum]的逻辑都会直接返回这个错误值,导致最终结果偏大

其他次要问题

你当前的递归分支逻辑是「选当前索引的硬币/不选当前索引的硬币,跳到下一个更小面值」,本质是按硬币顺序的贪心试探逻辑,不是标准的无限背包自上而下DP逻辑,虽然理论上可以覆盖所有组合,但结合错误的缓存逻辑会放大误差。

修正方案

把递归函数的返回值定义为「凑出参数传入的sum需要的最少硬币数」,去掉路径相关的curCoins参数,重新设计缓存逻辑即可:

int fncUtil(int dp[], int a[], int sum) {
    if(sum == 0) {
        return 0;
    }
    if(sum < 0) {
        return Integer.MAX_VALUE;
    }
    // 已计算过的子问题直接返回缓存值
    if(dp[sum] != 0) {
        return dp[sum];
    }
    int min = Integer.MAX_VALUE;
    // 遍历所有硬币,每个都可重复选择,匹配无限使用规则
    for(int coin : a) {
        int subRes = fncUtil(dp, a, sum - coin);
        if(subRes != Integer.MAX_VALUE) {
            min = Math.min(min, subRes + 1);
        }
    }
    dp[sum] = min;
    return min;
}
public int coinChange(int[] a, int sum) {
    if(sum == 0) return 0;
    int dp[] = new int[sum+1];
    int minCoins = fncUtil(dp, a, sum);
    return minCoins == Integer.MAX_VALUE ? -1 : minCoins;
}

如果要保留你原来的「按索引选/不选硬币」的分支逻辑,需要把缓存改为二维数组存储「剩余硬币索引+剩余金额」对应的最少硬币数,效率低于上述实现。

内容的提问来源于stack exchange,提问作者Chanfool21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 09:45:03