【算法题】322.零钱兑换-力扣(LeetCode)
【算法题】322.零钱兑换-力扣(LeetCode)
1.题目
下方是力扣官方题目的地址
给你一个整数数组 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.斐波那契数
斐波那契数 (通常用 F(n)
表示)形成的序列称为 斐波那契数列 。该数列由 0
和 1
开始,后面的每一项数字都是前面两项数字的和。也就是:
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
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 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)!