Day45:动态规划 爬楼梯(进阶版)LeedCode:322. 零钱兑换 279.完全平方数

爬楼梯(进阶版)

时间限制:1.000S  空间限制:128MB

题目描述

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

每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢? 

注意:给定 n 是一个正整数。

输入描述

输入共一行,包含两个正整数,分别表示n, m

输出描述

输出一个整数,表示爬到楼顶的方法数。

输入示例
3 2
输出示例
3
提示信息

数据范围:
1 <= m < n <= 32;

当 m = 2,n = 3 时,n = 3 这表示一共有三个台阶,m = 2 代表你每次可以爬一个台阶或者两个台阶。

此时你有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶段
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

思路:本题与完全背包类似 ,可翻译为1到m个物品,重量分别是1,2....m,每个物品可以取多次,装满背包有多少种方法,注意2,1和1,2,是两种,这是完全背包的排列问题,关于完全背包的组合和排列问题,移步至

Day44:动态规划 LeedCode 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ-CSDN博客

动态规划五部曲:

1.确定dp[j]的含义:

dp[j]:装满表示容量为j的物品,最多有几种方法

2.确定递推公式:

dp[j]+=dp[j-i];

3.dp数组如何初始化

dp[0]=1;如果dp[0]=1的话,后面推出来所以的值都为0

4.遍历顺序

一层循环遍历物品,一层循环遍历背包容量,哪层循环放外面?

Day44:动态规划 LeedCode 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ-CSDN博客这篇文章有讲

由于本题中不同顺序算不同方法,所以应该用遍历背包容量在外层循环,遍历物品在内部循环

5.举例推导

代码参考:

import java.util.*;
class Main{
    
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int m=in.nextInt();
        int[] dp=new int[n+1];
        //初始化
        dp[0]=1;
        //遍历容量/楼层
        for(int j=1;j<=n;j++){
            //遍历物品/步数
            for(int i=1;i<=m;i++){
                if(j>=i){
                    dp[j]+=dp[j-i];
                }
            }
        }
        System.out.println(dp[n]);
        
    }
}

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

思路:本题中每种硬币的数量是无限的,可以抽象成一道完全背包的问题

动态规划五部曲:

1.确定dp[j]的含义:

dp[j]:装满表示容量为j的物品,最少要几个物品

2.确定递推公式:

1).不放该硬币:dp[j]

2).放该硬币:dp[j-coins[i]]+1

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

3.dp数组如何初始化

求最少硬币数,为了防止覆盖,先将dp数组都设为Integer.MAX_VALUE

dp[0]=0;凑成0元只要0个硬币

4.遍历顺序

一层循环遍历物品,一层循环遍历背包容量,哪层循环放外面?

Day44:动态规划 LeedCode 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ-CSDN博客这篇文章有讲

由于本题中不同顺序算同一方法,所以应该用遍历背包容量在内层循环,遍历物品在外部循环

5.举例推导

代码参考:

class Solution {
    public int coinChange(int[] coins, int amount) {
          int[] dp=new int[amount+1];
          //初始化
          Arrays.fill(dp,Integer.MAX_VALUE);
          dp[0]=0;
          for(int i=0;i<coins.length;i++){
            for(int j=coins[i];j<=amount;j++){
               if(dp[j-coins[i]]!=Integer.MAX_VALUE)
                dp[j]=Math.min(dp[j],dp[j-coins[i]]+1);
            }
          }

          return dp[amount]==Integer.MAX_VALUE?-1:dp[amount];
    }
}

279. 完全平方数

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,149 和 16 都是完全平方数,而 3 和 11 不是。

示例 1:

输入:n = 12
输出:3 
解释:12 = 4 + 4 + 4

示例 2:

输入:n = 13
输出:2
解释:13 = 4 + 9

提示:

  • 1 <= n <= 104

思考:

本题和上一题类似,转化为完全背包问题

1.确定dp[j]的含义:

dp[j]:装满表示容量为j的物品,最少要几个物品

凑成整数n,至少需要几个完全平方数

2.确定递推公式:

1).不放i*i:dp[j]

2).放i*i:dp[j-i*i]+1

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

3.dp数组如何初始化

求最少完全平方数,为了防止覆盖,先将dp数组都设为Integer.MAX_VALUE

dp[0]=0;凑成0只要0个完全平方数

4.遍历顺序

一层循环遍历物品,一层循环遍历背包容量,哪层循环放外面?

Day44:动态规划 LeedCode 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ-CSDN博客这篇文章有讲

由于本题中不同顺序算同一方法,所以应该用遍历背包容量在内层循环,遍历物品在外部循环

5.举例推导

代码参考:

由于本题一定能凑出目标数,所以不需要判断dp[j-i*i]是否等于Integer.MAX_VALUE

class Solution {
    public int numSquares(int n) {
           int[] dp=new int[n+1];
           Arrays.fill(dp,Integer.MAX_VALUE);
           dp[0]=0;
           for(int i=1;i*i<=n;i++){
                for(int j=i*i;j<=n;j++){
                   dp[j]=Math.min(dp[j],dp[j-i*i]+1);
                }
           }
           return dp[n];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值