找硬币问题是一个经典的计算机科学中的优化问题,它涉及到动态规划这一重要的算法设计思想。问题描述为:给定一组不同面值的硬币,需要找到最少数量的硬币来组合成一个特定的金额。这个问题的核心在于如何有效地计算出在所有可能的组合中,哪一种组合所需的硬币数最少。
动态规划是一种解决最优化问题的有效方法,它通过将大问题分解为小问题,然后逐步构建最优解。在找硬币问题中,动态规划的思路是从最小的金额开始,逐步增加,每次都尝试找到当前金额下的最小硬币数量。这个过程可以表示为一个二维数组,其中数组的每个元素代表对应金额下的最小硬币数。
算法的设计通常包括以下几个步骤:
1. 初始化:创建一个数组 `coinsUsed`,用于存储从1到目标金额 `money` 每个金额对应的最小硬币数。初始时,假设每个金额都需要至少一个硬币,即 `coinsUsed[i] = i`。
2. 动态规划递推:对于每个金额 `cents`(从1到 `money`),遍历所有可用的硬币面值。如果当前面值 `values[kind]` 小于等于 `cents`,则尝试使用这个面值的硬币,加上 `cents - values[kind]` 的最小硬币数,看是否比当前已知的 `cents` 的最小硬币数更少。如果更少,则更新 `coinsUsed[cents]`。
3. 输出结果:遍历结束后,`coinsUsed[money]` 将包含目标金额 `money` 的最小硬币数,同时通过记录每一步的更新,也可以得到具体的硬币序列。
在给定的代码中,`coinChange` 函数实现了上述逻辑。它接收硬币面值数组 `values`、硬币种类数 `valuesCounts`、目标金额 `money` 和一个初始化的 `coinsUsed` 数组作为参数。通过两层循环,第一层遍历所有金额,第二层遍历所有硬币面值,计算并更新最小硬币数。函数会打印每一步的结果,显示每个金额对应的最小硬币数目。
输出结果展示了一个完整的找硬币过程,从金额1到目标金额63,给出了每一步的最小硬币数。例如,找钱25分可以用一枚25分的硬币,找钱30分可以用一枚25分和一枚5分的硬币,等等。
找硬币问题的解决方案利用了动态规划的优化能力,通过自底向上的方式避免了重复计算,实现了高效求解。这种问题在实际应用中非常常见,如在网络路由、任务调度、背包问题等场景中都有类似的应用。理解和掌握动态规划是提升算法能力的关键一步。