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

如何用递归实现最小硬币找零问题?

如何用递归实现最小硬币找零问题?

看起来你现在的代码只完成了贪心思路的第一步,完全没用到递归逻辑,所以才会只返回第一个面额的硬币。我来帮你调整成递归实现,同时解决贪心算法在部分场景下无法得到最优解的问题(比如你第二个测试用例里的[6,1,4]凑8,贪心会拿[6,1,1],但最优是[4,4])。

首先先明确你的需求:给定总金额和硬币面额,返回最少硬币数量的组合,用递归实现。

先分析你现有代码的问题

  • 没有递归调用:collect_coins函数只处理了第一个面额,没有对剩余金额和剩下的面额进行递归处理
  • 修改了原面额列表:denominations.pop(0)会直接修改传入的列表,导致后续逻辑出错
  • 贪心思路局限性:只取当前最大面额的最大数量,这种方法只在特定面额体系(比如美元硬币)下有效,无法应对所有场景

递归实现的核心思路

递归的关键是把大问题拆解成小问题:

  1. 对于当前面额,尝试使用0到最多能使用的数量(比如总金额18,面额10最多用1个)
  2. 对每种使用数量,递归处理剩余金额和剩下的面额
  3. 在所有可能的组合中,筛选出硬币数量最少的那个

修正后的递归代码

def r_change_money(total, denominations):
    # 先将面额降序排序,优先尝试大面额(优化递归效率,不影响结果正确性)
    sorted_denoms = sorted(denominations, reverse=True)
    
    def recursive_helper(remaining_amount, current_denoms):
        # 终止条件1:剩余金额为0,说明凑成了,返回空列表表示不需要更多硬币
        if remaining_amount == 0:
            return []
        # 终止条件2:剩余金额为负,或者没有可用面额了,返回None表示该组合无效
        if remaining_amount < 0 or not current_denoms:
            return None
        
        best_comb = None
        current_coin = current_denoms[0]
        # 计算当前硬币最多能使用的数量
        max_possible = remaining_amount // current_coin
        
        # 从最多数量往下尝试,能更快找到最优解(因为大硬币用得多的话数量更少)
        for count in range(max_possible, -1, -1):
            # 递归处理剩余金额和剩下的面额
            sub_comb = recursive_helper(remaining_amount - count * current_coin, current_denoms[1:])
            if sub_comb is not None:
                # 组合当前使用的硬币和子问题的结果
                current_comb = [current_coin] * count + sub_comb
                # 更新最优组合:要么是第一个有效组合,要么是更短的组合
                if best_comb is None or len(current_comb) < len(best_comb):
                    best_comb = current_comb
        
        return best_comb
    
    return recursive_helper(total, sorted_denoms)

# 测试用例1:预期输出 [10, 5, 1, 1, 1]
print(r_change_money(18, [1, 10, 5]))

# 测试用例2:预期输出 [4, 4](而非贪心的[6,1,1])
print(r_change_money(8, [6, 1, 4]))

代码解释

  • 外层函数先对面额降序排序,这样递归时优先尝试大面额,能更快找到短组合,提升效率
  • recursive_helper是核心递归函数,负责处理剩余金额和当前可用面额
  • 遍历当前硬币的所有可能使用数量,递归获取子问题的解,然后组合成完整的硬币列表
  • 每次都保留硬币数量最少的组合,最终返回最优解

运行这段代码,你就能得到预期的结果啦~

备注:内容来源于stack exchange,提问作者haltersweb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:39:35