二维动态规划,硬币

面试题 08.11. 硬币

硬币。给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码计算n分有几种表示法。(结果可能会很大,你需要将结果模上1000000007);

 

解题思路:二维动态规划,画矩阵。  

1. 行维:币种从1到4(按币值排序后逐渐增加), 列维:面值逐渐增加从0到n; 

  0 1 2 3 4 5 ... i-1 i

n

1  (+1分) 1 1 1 1 1 1        
2  (+5分) 1 1 1 1 1 2        
3  (+10分) 1 1 1 1 1 2        
4  (+25分) 1 1 1 1 1 2        

 

2. 动态方程:dp[row][col] = dp[row][col-coins[row]] + dp[row-1][col];

dp[row][col] 表示当增加到第row个币种时,获取col面值有多少种方式;有两种可能,一使用新加的币种,二是不使用新加的币种

一使用新加的币种,则可能性跟 “col-当前新加币值”时是一样的:dp[row][col-coins[row]] ;

二是不使用新加的币种,则可能性等于上一次币种凑出面值的可能性;dp[row-1][col];

3. 初始和边界条件:

当币种1时,各种面值可能性为1;

当面值为1时,各种币种可能性都为1;

特殊:当面值为0时,各种币种可能性都为1,考虑减币值case,比如dp[2][5] = dp[2][0] + dp[1][5]

当面值小于新加币值时,当前币值不能使用;

代码:

/**
 * @param {number} n
 * @return {number}
 */
var waysToChange = function(n) {
    const coins = [0,1,5,10,25];
    const dp = [[],[],[],[],[]];

    for(let coin = 1 ; coin <5;coin++){ // 币种
        for(let i= 0;i<=n;i++){ // 面值
            if(coin <= 1) {
                dp[coin][i]= 1;
            }else if(i <= 1){
                dp[coin][i]= 1;
            }else if(i >= coins[coin]){
                dp[coin][i] = dp[coin-1][i]+ dp[coin][i-coins[coin]];
            }else{
                dp[coin][i] = dp[coin-1][i]
            } 
        }
    }
    return dp[4][n] % 1000000007;
};

 

 

你可能感兴趣的:(基础算法)