硬币组合问题

  • 问题描述

1分2分5分的硬币,组成1角,共有多少种组合。
不妨将这个问题一般化,即给定一个非负数组,求有多少种组合可以组成n。

  • 解决方案(动态规划)
  1. dp[i][n]表示用前i + 1中硬币所能组成的n的种数
  2. 递推关系:dp[i][sum] = dp[i-1][sum - 0Vm] + dp[i-1][sum - 1Vm] + dp[i-1][sum - 2Vm] + … + dp[i-1][sum - KVm]; 其中K = sum / Vm。
  3. 返回值。返回dp[i][n]。
    代码如下:

 /**
     * n为总数,coins数组为硬币的面值,求有多少种组合
     * @param n
     * @param coins
     * @return
     */
    public static int coinGroups(int n,int[] coins){
        //dp[i][n]表示用前i + 1中硬币所能组成的n的种数
        int[][] dp = new int[coins.length][n + 1];
        for(int i = 0;i <= n;i ++){
            if(i % coins[0] == 0)
                dp[0][i] = 1;
        }
        for(int i = 1;i < coins.length;i ++){
            for(int k = 0;k <= n;k ++){
                for(int j = 0;j <= k / coins[i];j ++){
                    dp[i][k] = dp[i - 1][k - j * coins[i]] + dp[i][k];
                }
            }
        }
        return dp[coins.length - 1][n];
    }
  • 优化

方案1的空间复杂度较大,可以优化,代码如下:

 public static int coinGroups2(int n,int[] coins) {
        int[] dp = new int[n + 1];
        dp[0] = 1;
        for(int i = 0;i < coins.length;++i){
            for(int j = coins[i];j <= n;++j){
                dp[j] =dp[j]+dp[j-coins[i]];
            }
        }
        return dp[n];
    }
展开阅读全文
©️2020 CSDN 皮肤主题: 黑客帝国 设计师: 上身试试 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值