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

如何将Coin Change II的回溯代码转为带记忆化的自上而下递归版本?

Coin Change II 问题解法演进及问题求助

问题描述

给定不同面额的硬币数组coins和总金额amount,返回组成该金额的组合数,硬币可无限使用,无法组成则返回0,结果保证在32位有符号整数范围内。

初始回溯解法(逻辑正确但超时)

我采用回溯思路:每个硬币有两种选择,不选则索引+1,选则金额减去该硬币值且索引不变(可重复选取)。代码如下:

class Solution {
    private int count = 0;

    public int change( int amount, int[] coins) {
        Integer[] arr = Arrays.stream( coins)
                                .boxed()
                                .sorted( Comparator.reverseOrder())
                                .toArray( Integer[]::new);
        backtrack( arr, 0, amount);
        return count;
    }

    private void backtrack( Integer[] coins, int index, int amount) {
        if( index >= coins.length) {
            if( amount == 0) {
                ++count;
            }
        }
        else { // At every coin we have only two choices, 
               // either we take it or we skip it.
            backtrack( coins, index + 1, amount); 
               // This is the skip case, we are incrementing the index
               // by 1. And not taking that coin value into account
               // by not decrementing the current coin value from amount.
            if( coins[index] <= amount)
              backtrack( coins, index, amount - coins[index]);
               // We are taking that coin and subtracting the coin from the
               // amount, not incrementing the index as the same coin can be
               // considered multiple times, so as to be able to consider
               // it multiple times we are not incrementing the index.
        }
    }
}

该解法逻辑正确,但因递归次数过多导致超时(TLE)。

失败的记忆化递归尝试

我尝试将其转为带记忆化的自上而下递归版本,但未成功,尝试代码如下:

class Solution {
    private int count = 0;

    public int change(int amount, int[] coins) {
        int[] memo = new int[amount + 1];
        Arrays.fill( memo, -1);
        backtrack( coins, 0, memo, amount);
        System.out.println( "The content of the array is "
                            + Arrays.toString(memo));
        return memo[amount];
    }

    private void backtrack( int[] coins, int index, int[] memo, int amount) {
        if (index >= coins.length) {
            if (amount == 0) {
                ++count;
                return;
            }
        } else if (memo[amount] != -1){
            return;
        } else {
            backtrack( coins, index + 1, memo, amount);
            if (amount <= coins[index])
              backtrack( coins, index + 1, memo, amount - coins[index]);
            System.out.println( "The value of the count is ---> " 
                    + count 
                    + " and the value of the index is " + index);
            System.out.println( "The content of the array in backtrack is " 
                    + Arrays.toString( memo));  
            memo[amount] += count;  
        }
    }
}

需求

  • 保留全局count变量、返回值为void的回溯方法模板,通过最小修改使代码返回正确结果。
  • 了解从回溯到记忆化递归再到自下而上动态规划的完整演进步骤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:14:56