• home > theory > algorithm > leetcode >

    DP笔记(10):背包相关问题,零钱兑换

    Author:zhoulujun Date:

    背包相关问题宣讲一些典型案例



    零钱兑换兑换问题

    322 可以使用动态规划或回溯算法求解,而 518 通常使用动态规划求解。 本篇都用动态规划来解题

    零钱兑换

    给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

    你可以认为每种硬币的数量是无限的。

    示例 1:输入:coins = [1, 2, 5], amount = 11   输出:3    解释:11 = 5 + 5 + 1

    示例 2:输入:coins = [2],        amount = 3     输出:-1

    示例 3:输入:coins = [1],        amount = 0     输出:0

    当我一眼看完题目,我判断出这道题应该要用动态规划的思维来做,主要有两个原因:

    • 有可选择的东西(硬币)

    • 求到达一个目标数(amount)的最小硬币数(也就是最优解)

    解决动态规划问题,就是一个求最优解的问题,同时也是一个求最优子解的问题,在零钱问题中,求到amount的最小硬币数,就是求到amount前子问题的最小硬币数。

    前子问题是什么?

    我们先举个例子,输入: coins = [1, 2, 5], amount = 11  输出: 3

    目标数是11,那目标数的子问题是什么?

    没错,就是 amount - coins,在这道题中就是10, 9, 6

    那题就转换成了去求到达目标数10,到达目标数9,到达目标数6的最小硬币数,

    继续这样缩小范围,直到最基本的问题,也就是amount == 1的时候。

    我们采用自下而上的方式进行思考。仍定义 F(i) 为组成金额 iii 所需最少的硬币数量,假设在计算 F(i) 之前,我们已经计算出 F(0)−F(i−1) 的答案。 则 F(i) 对应的转移方程应为

    image.png

    前面我们说了,动态规划问题要找出状态和选择,

    状态是什么?

    状态就是到达这个目标数的最小硬币数!

    选择是什么?选择就是这个硬币我选还是不选?

    依据是什么?依据是能不能让我硬币数达到最小,

    比如到达目标数8,是让 5 + 1 + 1 + 1呢? 还是5 + 2 + 1呢?

    当然就是后者,这就是选择。

    dp数组记录的是什么?是状态。

    那可以转换成我们的状态转移方程了,

    // dp[i] 初始化为最大值
    dp[i] = MAX_VALUE
        
    dp[i] = min(dp[i - coins] + 1, dp[i])
    // i 代表当前目标数
    // coins代表硬币数额
    // +1,表示加上一个硬币数

    状态转移方程的问题解决了,这道题也就解决了一半了



    转载本站文章《DP笔记(10):背包相关问题,零钱兑换》,
    请注明出处:https://www.zhoulujun.cn/html/theory/algorithm/leetcode/9124.html