10.4.2 (python) 动态规划专题之换零钱 —— Coin Change & Perfect Squares

换零钱是一个典型的动态规划场景。

322. Coin Change

You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1

题目解析:

在现实场景中,换零钱用贪心算法就行~但是在题目中不可以。

动态规划的思路就是想换amount的零钱,我们需要从1开始步步为营,先解决每一个子问题。由于货币的单位未知,有可能许多面值无法兑换出来,需要做一些结果为-1的处理。

动态规划的思路大概是这样,代码有些啰嗦,可以精简一些。

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        if not coins:
            return -1
        n = len(coins)
        coins.sort()
        dp = [-1] * (amount+1)
        dp[0] = 0
        # 此题需要解决 无法组成的情况
        for i in range(1, amount+1):            
            min_ = i
            for coin in coins:
                if coin > i:
                    break
                if dp[i - coin] != -1:
                    min_ = min(min_, dp[i - coin])
            if min_ == i:
                dp[i] = -1
            else:
                dp[i] = min_ + 1
        return dp[-1]

279. Perfect Squares

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.

题目解析:

腚眼一看,这不也是在给n这个数值换零钱为 coins相当于一个个平方数。

当然由于平方等数学因素,我们可知道所有候选平方数,这道题也有非DP的解法,性能也不错,用一个队列直接去拼凑n。

这里我们只讨论DP算法,还是从1开始步步为营,对于每一个i来说,仍然是去 i - coin (这道题中coin相当于一个个平方数)的dp数组中查最小值。直接看代码吧,这个专题其实还比较简单的。

class Solution:
    def numSquares(self, n: int) -> int:
        dp = [0] * (n+1)
        sq = 0        
        for i in range(1, n+1):
            if i == (sq+1) ** 2:
                sq += 1
                dp[i] = 1
                continue
            # 否则的话 还是小于(sq+1)^2
            min_ = i
            stop = i // 2
            for j in range(sq, 0, -1):
                min_ = min(min_, dp[i-j*j])
                if min_ == 1:
                    break
            dp[i] = min_ + 1
        return dp[n]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值