dp小题目

今天面试问了个题目,有2元和3元的硬币无数个,组合成99元有多少种方式?
下面是我当时写的

# 99 2 3
# dp[j] = max{dp[j-2],dp[j-3]}
# dp[2] = 1 dp[3]=1 dp[1]=dp[0]= 0
def fun(total_amount):
    dp = [0 for i in range(total_amount+1)]
    dp[0] = 1
    j = 2
    while j < total_amount+1:
        dp[j] = dp[j-2]+dp[j-3]
        j+=1
    return dp

ans = fun(total_amount=7)
print(ans)

答案当然是不对的,问题在哪呢?乍一看好像dp[j] = dp[j-2]+dp[j-3]没毛病。但是这里忽略了一个问题,就是硬币的组合不含顺序。
比如以 7 元为例子,应该有 2 2 3这一种组合,但是我上面的代码计算的其实是 2 2 3,2 3 2, 3 2 2三种组合。
因此正确的算法应该注意硬币的顺序,比如数值小的硬币要在数值大的硬币前面。怎么做呢?只需要两层循环,外面的循环从小到大遍历硬币,里面的循环遍历总钱数。

def count_combinations(total_amount):
    coins = [2, 3]  # 可用的硬币面额
    dp = [0] * (total_amount + 1)  # 动态规划数组,dp[i] 表示凑成金额 i 的组合数量
    dp[0] = 1  # 初始化金额为 0 时的组合数量为 1
    for coin in coins:
        for i in range(coin, total_amount + 1):
            dp[i] += dp[i - coin]
	'''
	这样就避免了硬币的顺序问题,
	'''
    return dp[total_amount]

total_combinations = count_combinations(10)
print(total_combinations)

你可能感兴趣的:(算法岗面经,算法)