322.零钱兑换

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp =[inf]*(amount+1) #包含 0 和 amount 在内,一共有 amount - 0 + 1 = amount + 1 个不同的金额值需要存储结果。
        dp[0]=0  #dp[0] = 0 是一个确定的初始条件(凑成金额 0 需要 0 个硬币),它不需要是 inf,并且必须显式设置为 0 作为动态规划的起点。
        for i in range(1, amount+1):#外层循环遍历所有我们想要计算的金额,从 1 到 amount
            for j in coins:#内层循环遍历所有可用的硬币面额 j,如果通过其他的硬币 j' 找到了另一种凑成 i 的方法 (dp[i-j'] + 1)
                if i>=j:#确保我们当前考虑的金额 i 必须大于或等于硬币面额 j,否则我们不可能通过加上一个面额为 j 的硬币来凑成金额 i
                #比较 “当前已经找到的凑成 i 的最少硬币数 (dp[i])” 和 “通过使用硬币 j 凑成 i 所需的硬币数 (dp[i-j]+1)”,然后取两者中较小的那一个,作为更新后的 dp[i] 的值。这样就能确保 dp[i] 始终保存着凑成金额 i 的 最少 硬币数。dp[i] (在 min 函数的第一个参数位置): 这个代表在考虑使用硬币 j 之前,我们已经找到的凑成金额 i 的最少硬币数。在内层循环开始处理金额 i 时,dp[i] 的初始值是 inf(无穷大),表示暂时还没有找到任何方法凑成金额 i。随着内层循环遍历不同的硬币 j,dp[i] 会被更新为当前找到的最小值。
                    dp[i] = min(dp[i],dp[i-j]+1)
        return   dp[-1] if dp[-1]!=inf  else -1  
class Solution:
    def coinChange0(self, coins: List[int], amount: int) -> int:
        dp =[inf]*(amount+1) #包含 0 和 amount 在内,一共有 amount - 0 + 1 = amount + 1 个不同的金额值需要存储结果。
        dp[0]=0  #dp[0] = 0 是一个确定的初始条件(凑成金额 0 需要 0 个硬币),它不需要是 inf,并且必须显式设置为 0 作为动态规划的起点。
        for i in range(1, amount+1):#外层循环遍历所有我们想要计算的金额,从 1 到 amount
            for j in coins:#内层循环遍历所有可用的硬币面额 j,如果通过其他的硬币 j' 找到了另一种凑成 i 的方法 (dp[i-j'] + 1)
                if i>=j:#确保我们当前考虑的金额 i 必须大于或等于硬币面额 j,否则我们不可能通过加上一个面额为 j 的硬币来凑成金额 i
                #比较 “当前已经找到的凑成 i 的最少硬币数 (dp[i])” 和 “通过使用硬币 j 凑成 i 所需的硬币数 (dp[i-j]+1)”,然后取两者中较小的那一个,作为更新后的 dp[i] 的值。这样就能确保 dp[i] 始终保存着凑成金额 i 的 最少 硬币数。dp[i] (在 min 函数的第一个参数位置): 这个代表在考虑使用硬币 j 之前,我们已经找到的凑成金额 i 的最少硬币数。在内层循环开始处理金额 i 时,dp[i] 的初始值是 inf(无穷大),表示暂时还没有找到任何方法凑成金额 i。随着内层循环遍历不同的硬币 j,dp[i] 会被更新为当前找到的最小值。
                    dp[i] = min(dp[i],dp[i-j]+1)
        return   dp[-1] if dp[-1]!=inf  else -1 

    #recurison 自上而下的方法 
    def coinChange1(self, coins: List[int], amount: int) -> int:
        memo=[-1]*(amount+1)
        def solve(target):
            if target ==0:
                return 0
            if target<0: #代表着当前这条递归探索路径是无效或不可能的。
                return inf 
            if memo[target] !=-1:#我们之前是不是已经计算过凑成金额 target 最少需要多少硬币了?if 是。那么这行代码就直接从备忘录 memo 中取出之前存好的结果,并将其返回给上一层调用 solve 的地方。
                return memo[target]
            min_needed =inf 
            for coin in coins:
                #递归调用,解决子问题, 凑够target-coin 需要的最少硬币
                sub_result =solve(target-coin)
                #如果子问题有解,  不是无穷大  对应上面 if target<0 的情况 
                if sub_result !=inf :
                    #更新当前target 最小硬币组合 子问题的解+当前的coin这枚硬币
                    min_needed =min(min_needed,sub_result+1)
            memo[target]=min_needed
            return min_needed
        result =solve(amount)
        return result if result !=inf else  -1 
    #recurison 的递归,调用 lru_cache缓存方法,自动实现备忘录功能
    def coinChange(self, coins: List[int], amount: int) -> int:
        # 使用 lru_cache 自动实现备忘录功能
        @functools.lru_cache(maxsize =None)
        def sovle(target):
            if target ==0:
                return 0
            if target <0:
                return inf 
            min_needed=inf 
            for coin in coins:
                sub_result=sovle(target-coin)
                if sub_result !=inf :
                    min_needed=min(min_needed,sub_result+1)
            return min_needed
        # ---- 主函数逻辑 ----
        result = sovle(amount)
        return result if result != float('inf') else -1    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值