自学内容网 自学内容网

【算法题】322.零钱兑换-力扣(LeetCode)

【算法题】322.零钱兑换-力扣(LeetCode)

1.题目

下方是力扣官方题目的地址

322.零钱兑换

给你一个整数数组 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

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 231 - 1
  • 0 <= amount <= 104

2.题解

这题和力扣官网的

509.斐波那契数

70. 爬楼梯

都差不多

在这题之前我们先来看看这两题

509.斐波那契数

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 01 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n)

示例 1:

输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

输入:n = 3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

输入:n = 4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3

思路

斐波那契数列比较经典,我们知道它的递推式:

F(n) = F(n - 1) + F(n - 2),其中 n > 1

由此看来,F(n)的结果是与F(n-1)F(n-2)有关的。

利用动态规划的思想,我们只需要将F(n-1)F(n-2)的值存入一个数组中,用到时直接拿来用就是了

class Solution(object):
    def fib(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n==0:return 0
        if n<=2:return 1
        dp=[0]*n
        dp[0],dp[1]=1,1
        for i in range(2,n):
            dp[i]=dp[i-1]+dp[i-2]
        return dp[-1]

70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 12 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例 1:

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶

示例 2:

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶

提示:

  • 1 <= n <= 45

思路

本题完全可以类比斐波那契数列,我使用dp[i]表示爬到第i阶楼梯的方法,那么我们有两种方式爬到第i阶:

在dp[i-1]时爬1阶;

在dp[i–2]时爬两阶

所以很容易得出递推式:

dp[i]=dp[i-1]+dp[i-2]

class Solution(object):
    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n==1:return 1
        if n==2:return 2
        dp=[0]*(n+1)
        dp[1]=1
        dp[2]=2
        for i in range(3,n+1):
            dp[i]=dp[i-1]+dp[i-2]
        return dp[n]

类比前面两题,在来做本题322.零钱兑换,就显得非常轻松了

本题思路

我们设dp[i]表示当总金额为i时凑成总金额所需的 最少的硬币个数

我们以coins = [1, 2, 5], amount = 11为例,我们知道,硬币就1,2,5这三种,所以当总金额为i时的最少硬币个数的得来就有三种情况:

dp[i-1]时再来拼凑面值1的硬币;

dp[i-2]时再来拼凑面值2的硬币;

dp[i-5]时再来拼凑面值5的硬币

如图所示:

在这里插入图片描述

所以就能得出递推式:

dp[i]=min(dp[i-coin]+1,dp[i])

coin代表的就是硬币的面值

我们将这题和爬楼梯做对比,发现:

我们的coins[1,2,5]就相当于爬楼梯中我们一次能爬的阶梯的阶数[1,2]

只不过爬楼梯是给定的[1,2],而本题在变化而已,写代码时,只要注意捕获coins的变化就行了

Python代码

class Solution(object):
    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
        dp=[float('inf')]*(amount+1)  # 初始化dp
        dp[0]=0
        for i in range(1,amount+1):
            for j in coins:           # j代表硬币的面值,由于coins的不确定性,所以得增加一个for来捕获coin(每个硬币的面值)
                if i-j>=0:            # 检验总额是否大于硬币面值
                    dp[i]=min(dp[i-j]+1,dp[i]) # 如果大于,才能就行递推
        return dp[-1] if dp[-1] != float('inf') else -1

3.结语

本人资历尚浅,发博客主要是记录与学习,欢迎大佬们批评指教!大家也可以在评论区多多交流,相互学习,共同成长。


原文地址:https://blog.csdn.net/Janium/article/details/142282413

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!