• Day 45 | 70. 进阶爬楼梯 & 322. 零钱兑换 & 279.完全平方数


     70. 进阶爬楼梯

    完全背包解题思路: 

    爬楼梯原题目是一次只能爬1/2层台阶,若改为一次可以爬m个台阶,即为完全背包的排列问题

    每次可以跳[1,i],跳到第j阶,共有dp[j]种方法

    递推公式:dp[j]+=dp[j-nums[i]]

    因为是排列问题,因此先遍历容量(跳1/2层台阶),再遍历背包(跳到了多少层台阶)。容量从前往后计算。

    1. public int combinationSum4(int[] nums, int target) {
    2. int[] dp=new int[target+1];
    3. dp[0]=1;
    4. for(int j=0;j<=target;j++){
    5. for(int i=0;i
    6. if(j-nums[i]>=0){
    7. dp[j]+=dp[j-nums[i]];
    8. }
    9. }
    10. }
    11. return dp[target];
    12. }

    322. 零钱兑换 

    完全背包解题思路:

            硬币无限个,凑成总金额(装满背包):完全背包问题

            本题求的是最少硬币个数,可转换为[0,i[个硬币,凑成金额j,所需钱币最少为dp[j]

    每次遍历时有两种选择:

    ①取:dp[j]=dp[j-nums[i]+1  (凑成金额为j-nums[i[所需的最少硬币再加1即为凑成j的最少硬币数)

    ②不取,dp[j]=dp[j]

    因为求的是最少硬币数,每次对这两个数取小即可。

    因此,状态转移方程为:dp[j]=Math.min(dp[j],dp[j-nums[i]]+1);

    数组的初始化

            所有dp[j]都先定义为为最大值。dp[0]=0,当金额为0时要0个硬币。

    数组的遍历顺序

            完全背包问题,本题是要求最少硬币数量,硬币是组合数还是排列数都无所谓!所以两个for循环先后顺序怎样都可以。但是遍历容量要从前向后遍历,满足一个硬币可放多次的条件。

    1. int max=Integer.MAX_VALUE;
    2. int[] dp=new int[amount+1];
    3. for(int j=0;j<=amount;j++){
    4. dp[j]=max;
    5. }
    6. dp[0]=0;
    7. for(int i=0;i
    8. for(int j=coins[i];j<=amount;j++){
    9. //当dp[j-coins]不为max时比较才有意义
    10. if(dp[j-coins[i]]!=max){
    11. dp[j]=Math.min(dp[j],dp[j-coins[i]]+1);}
    12. }
    13. }
    14. return dp[amount]==max?-1:dp[amount];

    279. 完全平方数

    完全背包解题思路:

            每个物品为i*i(平方数),物品有无限个,凑成和为j,最小有dp[j]个完全平方数。

    ①确定dp数组以及下标含义

            dp[j]:每个物品大小为i*i,装满容量j的背包,最少个数为dp[j]个。

    ②确定递推公式

            遇上题相同,求的是最小个数。

    取的时候为装满容量j-i*i的最少个数+1(当前这个数);不取即为dp[j]

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

    ③dp数组如何初始化

          所有dp[j]都先定义为为最大值。dp[0]=0,

    ④确定遍历顺序

            与上一题相同。

            本题是要求最少平方数的个数,是组合数还是排列数都无所谓!所以两个for循环先后顺序怎样都可以。但是遍历容量要从前向后遍历,满足一个数可放多次的条件。

    ⑤举例推导dp数组

       n=5 :

    1. public int numSquares(int n) {
    2. int[] dp = new int[n + 1];
    3. int max = Integer.MAX_VALUE;
    4. for (int j = 0; j <= n; j++) {
    5. dp[j] = max;
    6. }
    7. dp[0] = 0;
    8. for (int i = 1; i * i <= n; i++) {
    9. for (int j = i * i; j <= n; j++) {
    10. if (dp[j - i * i] != max) {
    11. dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
    12. }
    13. }
    14. }
    15. return dp[n];
    16. }

  • 相关阅读:
    【WebSocket 第一篇】从一个WebSocket连接说起
    单例模式java
    CSP-J1 CSP-S1 初赛 第1轮 数学问题(数论、排列组合等)
    商场公司怎样利用智能机器人快速联结却不干扰底层
    无代码开发平台通讯录导出入门教程
    Revit SDK 介绍:CreateAirHandler 创建户式风管机
    ELMo模型、word2vec、独热编码(one-hot编码)的优缺点进行对比
    PHP文件读写
    springboot之Filter的URI匹配规则
    C++之 内联函数
  • 原文地址:https://blog.csdn.net/m0_56579820/article/details/127700979