一、爬楼梯(进阶版)
1.1 题目
题目描述
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
输入描述
输入共一行,包含两个正整数,分别表示n, m
输出描述
输出一个整数,表示爬到楼顶的方法数。
输入示例
3 2
输出示例
3
1.2 题目链接
1.3 解题思路与过程想法
(1)解题思路
# 分析:这道题是 70.爬楼梯 的进阶版,对于每次爬楼的最多阶数是个不定值 n。是个典型的背包的排列问题。
排列问题:1+2+1 和 2+1+1 是两种不同方法
数组:爬到 i 阶,有 dp[i] 种方法
递推关系:求组成的方法数——————dp[j] += dp[j-i],
求背包装载的最大“价值” ——dp[j] = max(dp[j], dp[j-weight[i]]+value[i])
求背包装载的最少“数量” ——dp[j] = min(dp[j], dp[j-weight[i]]+1)
初始化:求组成的方法数——dp[0] = 1
其他值初始化———初始化不影响覆盖的值,求最大-->初始化最小;
求最小-->初始化无穷大值
遍历顺序:因为是排列问题,所以先遍历背包容量,后遍历物体
此处 weight[i] 对应着 本次爬楼的阶数
value[i] 对应着 一次爬楼
(2)过程想法
比较经典,思路也比较好想,但需注意是排列问题
1.4 代码
def up(n,m) -> int:
# 物品是每次爬的楼梯数,可重复---->完全背包
# 背包容量 n,物品 1~m
# 数组:爬到 i 阶,有 dp[i] 种方法
dp = [0] * (n+1)
# 递推关系:dp[j] += dp[j-i]
# 初始化:求方法数,一般初始化 dp[0] = 1,若是0则后续将全是 0
dp[0] = 1
for j in range(1,n+1): # 遍历背包
for i in range(1,m+1): # 遍历物体
if j >= i:
dp[j] += dp[j-i]
return dp[n]
if __name__ == "__main__":
# 从键盘端一次性连续读取两个数字
inputs = input()
# 将输入拆分为两个数字
num1, num2 = map(int, inputs.split())
print(up(num1,num2))
二、零钱兑换
2.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] <= 2^31 - 1
0 <= amount <= 10^4
2.2 题目链接
2.3 解题思路与过程想法
(1)解题思路
# 数组:构成总金额 j 所需的最少硬币数 dp[j]
# 初始化:初始一个不会覆盖其他值的原始值(求最小,赋无穷大)
# 递推关系:dp[j] = min(dp[j],dp[j-coin]+1)
# 完全背包的组合问题:先遍历物体,后遍历背包容量
(2)过程想法
针对纯完全背包问题变化不是很大,代码比较好写
2.4 代码
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
# 完全背包:组合问题
# 数组:构成总金额 j 所需的最少硬币数 dp[j]
# 初始化:初始一个不会覆盖其他值的原始值
dp = [float('inf')] * (amount+1)
# 递推关系:dp[j] = min(dp[j],dp[j-coin]+1)
# 初始化
dp[0] = 0
# 举例递推
for coin in coins: # 遍历物品
for j in range(coin,amount+1): # 遍历背包
dp[j] = min(dp[j],dp[j-coin]+1)
return dp[amount] if dp[amount] != float('inf') else -1
三、完全平方数
3.1 题目
给你一个整数 n
,返回 和为 n
的完全平方数的最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1
、4
、9
和 16
都是完全平方数,而 3
和 11
不是。
示例 1:
输入:n = 12 输出:3 解释:12 = 4 + 4 + 4
示例 2:
输入:n = 13 输出:2 解释:13 = 4 + 9
提示:
1 <= n <= 10^4
3.2 题目链接
3.3 解题思路与过程想法
(1)解题思路
分析:整个题目的变体主要在于“完全平方数”,为了便于遍历,以其需“平方”的数为遍历数。
# 数组:i 最少可由 dp[i] 个完全平方数组成
# 初始化:初始一个不会覆盖其他值的原始值(求最小,赋无穷大)
# 递推关系:dp[j] = min(dp[j],dp[j-i*i]+1)
# 完全背包的组合问题:先遍历物体,后遍历背包容量
(2)过程想法
分析出变化的关系,代码是很好写的
3.4 代码
class Solution:
def numSquares(self, n: int) -> int:
# 完全背包问题-组合问题
# 数组:i 最少可由 dp[i] 个完全平方数组成
dp = [float('inf')] * (n+1)
# 递推关系:dp[j] = min(dp[j],dp[j-i*i]+1)
# 初始化
dp[0] = 0
for i in range(n//2+1): # 遍历物体
for j in range(i*i,n+1): # 遍历背包
dp[j] = min(dp[j], dp[j - i*i]+1)
# 处理边界情况
return dp[n] if n != 1 else 1