day45|● 70. 爬楼梯 (进阶) ● 322. 零钱兑换 ● 279.完全平方数

70. 爬楼梯 (进阶)

爬楼梯:每次可爬一阶或二阶,用斐波拉契。

一步一个台阶,两个台阶,三个台阶,…,直到 m个台阶。问有多少种不同的方法可以爬到楼顶n呢? 1阶,2阶,…
m阶就是物品,楼顶就是背包。

  1. dp数组含义:dp[i]:爬到有i个台阶的楼顶,有dp[i]种方法。
  2. 递推公式:dp[i] += dp[i - nums[j]];
    dp[i] += dp[i - j]
  3. 初始化:dp[0] 一定为1,dp[0]是递归中一切数值的基础所在
  4. 遍历顺序:完全背包,求排列总和,物品的顺序很重要(先背包再物品)
class Solution {
    public int climbStairs(int n) {
        int[] dp = new int[n + 1];
        int m = 2; //有兩個物品:itme1重量爲一,item2重量爲二
        dp[0] = 1;

        for (int i = 1; i <= n; i++) { // 遍历背包
            for (int j = 1; j <= m; j++) { //遍历物品
                if (i >= j)  //當前的背包容量 大於 物品重量的時候,我們才需要記錄當前的這個裝得方法(方法數+)
			       dp[i] += dp[i - j];
            }
        }

        return dp[n];
    }
}

322. 零钱兑换

You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.
Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
You may assume that you have an infinite number of each kind of coin.
Input: coins = [1,2,5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1

  1. dp[i]:make up i所需要的最少硬币数。
  2. 求达成总和需要的最少硬币数:dp[j] = Math.min(dp[j], dp[j-coins[i]]+1);
    dp[j] 要取所有 dp[j - coins[i]] + 1 中最小的。
  3. 初始化:除了dp[0] = 0; 其他都为最大值,才能去小
  4. 遍历顺序:每个物品可以重复取,所以正向遍历背包。但是本体需要的是最少硬币数,不是组合总和或者排列总和,所以有没有顺序都可以。物品背包的内外循环也可以颠倒。
  5. 这里需要注意递推的限制条件,就是max integer代表没有办法凑成当前的dp[i],所以不用考虑进比较。
class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount+1];
        dp[0] = 0;
        for (int i = 1; i < dp.length; i++) {
            dp[i] = Integer.MAX_VALUE;
        }
        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.完全平方数

Given an integer n, return the least number of perfect square numbers that sum to n.
Input: n = 12
Output: 3
Explanation: 12 = 4 + 4 + 4.

dp[j]:和为j的完全平方数的最少数量为dp[j]
dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。

最少需要多少完全平方数来达成当前总和。

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n+1];
        dp[0] = 0;
        for (int i = 1; i < n+1; i++) {
            dp[i] = Integer.MAX_VALUE;
        }
        for (int i = 0; i <= n; i++) { // 物品
            for (int j = 1; j <= n; j++) { // 背包
                if (i*i <= j && dp[j-i*i] != Integer.MAX_VALUE) {
                    dp[j] = Math.min(dp[j], dp[j-i*i] + 1);
                }
            }
        }
        return dp[n];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值