[LeetCode题解] 322. 零钱兑换

2 篇文章 0 订阅
1 篇文章 0 订阅

题目链接: https://leetcode-cn.com/problems/coin-change/.
提供两种思路:

解法一. DP
执行用时 : 892 ms, 在所有 Python 提交中击败了77.35%的用户
内存消耗 :12.1 MB, 在所有 Python 提交中击败了33.04%的用户

class Solution(object):
    def coinChange(self, coins, amount):
        dp = [float('inf')] * (amount + 1)
        dp[0] = 0
        for i in range(1, amount + 1):
            for coin in coins:
                if coin > i:
                    continue
                dp[i] = min(dp[i], dp[i-coin] + 1)
        return dp[amount] if dp[amount] != float('inf') else -1

JAVA Source Code
class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount+1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for(int i = 1; i <= amount; i++) {
            for(int j = 0; j < coins.length; j++) {
                if((i >= coins[j]) && (dp[i - coins[j]] != Integer.MAX_VALUE)) {
                    dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
                }
            }
        }
        return (dp[amount] == Integer.MAX_VALUE) ? -1: dp[amount];
    }
}

假设F(A)代表amount = A的时候其硬币组合的最小数。
F(A) = min(F(A-C0), …, F(A-Cn)) + 1
其中Ci为ith 个硬币面值。
由此可得状态转移方程。

解法二. DFS + 贪心
执行用时 : 200 ms, 在所有 Python 提交中击败了98.98%的用户
内存消耗 : 11.9 MB, 在所有 Python 提交中击败了80.87%的用户

class Solution(object):
    coins = []
    res = float('inf')
    def coinChange(self, coins, amount):
        self.coins = sorted(coins, reverse=True)
        for i in range(len(self.coins)):
            self.help(i, 0, amount)
        return self.res if self.res != float('inf') else -1

    def help(self, coin_i, coin_count, amount):
        if amount == 0:
            self.res = min(self.res, coin_count)
            return
        for i in range(coin_i, len(self.coins)):
            if (self.res - coin_count) * self.coins[i] < amount: break
            if self.coins[i] > amount: continue
            self.help(i, coin_count + 1, amount - self.coins[i])

利用self.res记录最终值。
help中有两个剪枝方法:

  1. 当(目前的结果 - 当前的硬币的数量) * 可使用的硬币的最大值 < amount,直接break
  2. 当前的硬币面值 > amount,continue(因为coins是reverse sort)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值