代码随想录第四十五天 | 爬楼梯(进阶)&&零钱兑换&&完全平方数
70.爬楼梯(进阶)
文章:22. 爬楼梯(进阶版)
【思路】
本题和力扣上面那题不太一样,那题每步只能走1或2步,本题是1<=m<=n,m阶可选。
以及、跨越的阶数是没有数量限制的,因此我们采用完全背包。
1.确认数组及其下标含义
dp[i]:爬到第i阶有dp[i]种方法
2.递推公式
题目求的是爬上n层有多少种方法,也就是求总和
那么递推公式自然是:dp[i]+= dp[i-j]
3.初始化数组
因为递推公式是累加递推,所以我们需要将dp[0]初始化为1,这样后续的累加才有作用。
dp[0]= 1
4.确定遍历顺序
完全背包,且求的是组合数,对物品和背包的遍历顺序没有要求,两个都可以啊。
- Java实现
woooooo发现java的acm模式不会敲了 ! o !
1 | import java.util.Scanner; |
- Go实现
1 | package main |
322.零钱兑换
文章:23. 零钱兑换
题目:322. 零钱兑换
【思路】
题目说每种硬币的数量是无限的,也就是说该题是完全背包。
五部曲如下:
1.确定dp数组及其下标的含义
dp[j] : 凑成金额为j的钱币最小个数为dp[j],钱币的价值为1(values = 1)
2.确定递推公式
凑足总额为j-coins[i]的最小个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] +1就是dp[i],而且需要获取的个数最小:
因此推出递推公式为:dp[j] = min(dp[j] , dp[j-coins[i]] + 1)
3.数组初始化
首先,凑足总金额为0所需的钱币个数一定是0,那么dp[0] = 0
考虑到递推公式的特性,dp[j]必须被初始化为一个最大的数,否则就会在min(dp[j],dp[j-coins[i]]+1)中被初始值覆盖,因此下标非0的元素都应该是最大值。
4.确定遍历顺序
本题求钱币的最小个数,那么钱币的有无顺序都不会影响钱币的最小个数。
也就是都可以!
5.举例推导。。
- Java实现
1 | class Solution { |
- Go实现
1 | func coinChange(coins []int, amount int) int { |
279.完全平方数
文章:24. 完全平方数
题目:279. 完全平方数
【思路】
完全平方数是物品(可以无限使用),凑的正整数n就是背包,问凑满这个背包最少需要多少个物品
1.确定dp数组及其下标含义
dp[j]:和为j 的完全平方数的最少数量为dp[j]
2.确定递推公式
dp[j]可以由dp[j - ii]推出,**dp[j] = min(dp[j] , dp[j - i i] +1)
*i i 看作是nums[i],+1看作是values[i]
3.dp数组如何初始化
dp[0]表示和为0的完全平方数的最小数量,即dp[0] = 0
非零下标:从递推公式中可以看出,我们每次求的都是最小的dp[j],也就是说我们需要初始化为最大值,避免被初始值覆盖
4.确定遍历顺序
完全背包,求凑满背包需要多少个物品,求的是个数,也就是无论是背包在外循环物品在内循环、还是物品在外循环背包在外循环都是可以的!
5.举例推导。。
- Java实现
1 | class Solution { |
- Go实现
1 | func numSquares(n int) int { |
【算法总结】
- 爬楼梯:使用完全背包,爬的阶数可以被无限使用。通过累加每一层的阶数得到dp[n]
- 零钱兑换:使用完全背包,零钱可以被无限使用。通过求dp[j]和dp[j-num[i]]+1的最小值,来获得dp[n]
- 完全平方数:使用完全背包,完全平方数可以被无限使用。通过求dp[j]和dp[j-i*i]+1的最小值,来获得dp[n]
【语法总结】
Java
1
2
3
4//求最大值
int max = Integer.MAX_VALUE;
//main函数
public static void main(String[]args){}Go
1
2
3
4
5//求最大值
max:=Math.MaxInt
//输入
var m int
fmt.Scan(&m)