leetcode-zgd-day45-70.爬楼梯(进阶)/322.零钱兑换

122 阅读2分钟

70.爬楼梯(进阶)

题目链接:70. 爬楼梯 - 力扣(LeetCode)

解题思路:

 class Solution {
     public int climbStairs(int n) {
         /**
          *  还有一种题目的理解方式,数字n可以分为多少种由1和2组成的排列
          *  1.dp[j] 凑够j一共有多少种方案
          *  2.dp[j] = dp[j] + dp[j - step[i]];
          *  3.dp[0] = 1
          *  4.完全背包:正向循环
          */
         int[] step = new int[]{1,2};
         int[] dp = new int[n + 1];
         dp[0] = 1;
         for(int j = 0; j <= n; j++){
             for(int i = 0; i < step.length; i++){
                 if(j >= step[i]) dp[j] = dp[j] + dp[j - step[i]];
             }
         }
         return dp[n];
     }
 }

322.零钱兑换

题目链接:322. 零钱兑换 - 力扣(LeetCode)

解题思路:

这个题需要注意的点就是,初始化为什么全都赋值成最大值.

因为这个题要求最少的硬币个数,体现在递推关系式中,就是要求两者之中最小的,如果初始化的时候都初始化为0,那么不管怎么比较,结果都为0,就导致,dp数组递推到最后都是0.所以初始化的时候要全初始化为最大值,只有最初的dp[0] = 0 才初始化为0.

 class Solution {
     public int coinChange(int[] coins, int amount) {
         /**
          * 1.dp[j] 凑成数字j最少需要多少个硬币
          * 2.dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1)
          * 3.dp[0] = 0;
          * 4.不限制硬币使用数量,完全背包正向循环
          */
         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);
                 }
             }
         }
         if(dp[amount] == Integer.MAX_VALUE) return -1;
         return dp[amount];
     }
 }

279.完全平方数

题目链接:279. 完全平方数 - 力扣(LeetCode)

解题思路:

该题目的物品就是每个完全平方数,完全没有必要先将完全平方数都算出来存起来,直接利用外层循环的index就可以了。

因为是求最少个数的完全背包问题,所以初始化的时候,除了第一个元素初始化为真实值0,其他元素都初始化成Integer.MAX_VALUE,同时在递推dp数组的时候,要在外面嵌套一层if判断,确认要比较的元素是否是初始化时候的值,如果是,就代表目前还没有完全平方数能够组合出该数字,就不和dp[j]进行比较了。如果不是,再与dp[j]进行比较取最小。

 class Solution {
     public int numSquares(int n) {
         /**
          * 这个题和零钱兑换是类似的,都是要返回最小组成数字的个数。
          * 1.dp[j] 和为n的完全平方数的最小数量
          * 2.dp[j] = Math.min(dp[j], dp[j - Math.pow(i,2)] + 1)
          * 3.dp[0] = 0; dp[j] = Integer.MAX_VALUE
          * 4.完全背包问题正向遍历
          */
         int[] dp = new int[n + 1];
         Arrays.fill(dp, Integer.MAX_VALUE);
         dp[0] = 0;
         for(int i = 1; i <= n; i++){
             int k = (int)Math.pow(i,2);
             for(int j = k; j <= n; j++){
                 if(dp[j - k] != Integer.MAX_VALUE){
                     dp[j] = Math.min(dp[j], dp[j - k] + 1);
                 }
             }
         }
         return dp[n];
     }
 }