LeetCode322.零钱兑换-DP数组的迭代解法(动态规划)-Python


题目

在这里插入图片描述


一、解题思路

动态规划:一般用于求最值,核心在于找 状态转移方程式
动态规划问题一定具备 最优子结构,通过求解子结构的最优解 从而获得原问题的最优解

例子: conis=[1,2,5] amount=7

1.原问题:凑金额7 所需要的最少硬币数是多少?

1.1 子问题:凑金额6 所需要的最少硬币数是多少?
1.1.1 子问题 凑金额5 所需要的最少硬币数是多少?

1.1.1… 子问题 凑金额1 所需要的最少硬币数是多少?
我们需要做的就是 求出每个子问题的答案 。
求每个子问题的这个过程,其实就是 状态转移方程式 因为过程一样,所以就可以用这个方程式来表示

2.初始化一个dp数组用于存放子问题的答案
dp数组除第一个元素外,其余所有元素均为正无穷。因金额为0时,所需硬币数为0,所以将dp[0]=0

以下为求解子问题的过程:
金额为1时:1+dp[0]=1 1:代表1个1元面值的硬币 dp[0]:凑金额0 需要的最少硬币数0 1:凑金额1需要的硬币数为1 min(1+dp[0],dp[1])—> 1 dp[1]最开始为正无穷
答案:1
金额为2时:1+dp[1]=2 1:代表1个1元面值的硬币 dp[1]:凑金额1 需要的最少硬币数1 2:凑金额2需要的硬币数为2 min(1+dp[1],dp[2])—> dp[2]=2
2+dp[0]=1 1:代表1个2元面值的硬币 dp[0]:凑金额0 需要的最少硬币数0 1:凑金额2需要的硬币数为1 min(1+dp[0],dp[2])—>min(1,2)—> dp[2]=1
答案:1

以上总结如下:
dp[2]=min(1+dp[2-1],dp[2]) —>dp[2]=2 2-1:表示金额2减去coins中遍历的面值金额1 【差值要大于等于0,才能凑】
dp[2]=min(1+dp[2-2],dp[2]) —>dp[2]=1 2-2:表示金额2减去coins中遍历的面值金额2

因此状态转移方程式为: dp[n]=min(1+dp[n-coins[i]],dp[n])

二、代码

代码如下:

    def coinChange(self, coins: List[int], amount: int) -> int:
        res=float('INF')     # 代表正无穷
        dp=[res]*(amount+1)    #dp数组的定义:当目标金额为i时,至少需要dp[i]枚凑出
        dp[0]=0    # 金额为0时,结果则为0
        # amount=7  从金额1开始,凑金额1 2 3 4 5 6 7 ,每种金额需要的最少硬币数
        for i in range(1,amount+1):   
            # 遍历已有的金额面值 coins=[1,2,5]
            for coin in coins:
                diff=i-coin    #只有金额数大于等于已有的面值数 才能进行凑数  
                if diff>=0:
                    # 这里涉及到 状态转移方程式  金额数=某金额面值的张数y+dp[x]   
                    # 初dp[0]=0,其余dp[x]初已经始化为正无穷 但在求每种金额数需要的最少硬币数时,会将其最优值保存到相应的dp数组里
                    dp[i]=min(1+dp[diff],dp[i])
        if dp[amount]!=inf:    # 如果dp数组的最后一个数据不为inf,所以此时保存的数据已经改变,是凑出该金额需要的最少数量
            return dp[amount]
        else:
            return -1



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值