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

一、70. 爬楼梯 (进阶)

了解到了爬楼梯新的解法,感觉这种解法其实更容易理解。

之所以可以转化:

  1. 可以选择的物品 0、1
  2. 可以选择任意多次,数量不限
  3. 有一个目标值——最终的楼梯阶数

所以是完美契合使用完全背包来求解排序的种类数。

以下是代码部分:

	//思路: 完全背包,求排序种类
    public int climbStairs(int n) {

        int[] dp = new int[n+1];

        dp[0] = 1;

        int[] nums = new int[]{1,2};

        for (int i = 0; i < n+1; i++) {
            for (int j = 0; j < nums.length; j++) {
                //踩坑:这里时小于等于
                if( nums[j] <= i)
                    dp[i] += dp[i - nums[j]];
            }
        }

        for (int i = 0; i < n+1; i++) {
            System.out.print(dp[i] + " ");
        }
        return dp[n];
    }

二、322. 零钱兑换

这道题需要注意的地方:

  1. dp[]数组表示取得 i 值所需的最少金币数 dp[i]
  2. 递推公式是进行一个比较,比较的双方是:不加当前物品 i 所得的dp[j]、 加上当前物品 i 所得的dp[j - coins[i] ] + 1。注意这里有 +1 ,因为已经是算上当前物品了。
  3. 初始化时,dp[0] = 0,表示0面值不需要金币,所以是0个。但其他数值要初始化成最大的整型,因为后续要比较大小,这里若初始化为0为影响到比较结果。
  4. 最需要注意的一点:如果dp[j - coins[i]] 为初始值,则跳过,证明没有方案可以实现价值等于j - coins[i] 。

以下是代码部分:

public class 零钱兑换322 {

    public int coinChange(int[] coins, int amount) {

        //表示取得当前面值所需的最少金币数
        int[] dp = new int[amount+1];

        //0面值不需要金币,所以是0个
        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+1; j++) {

                //踩坑:如果减去coins[i]为初始值,则跳过,证明没有方案可以实现价值等于j - coins[i]
                if( dp[j - coins[i]] != Integer.MAX_VALUE )
                    dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);   //上一行的dp[j](不加物品i)和当前行加上物品i的dp[i]进行比较
            }
        }

        //这里还要判断最后的值是否依旧是原始值,若是,证明没有可行方案
        if( dp[amount] == Integer.MAX_VALUE)
            return -1;
        return dp[amount];
    }
}

三、279.完全平方数

这道题其实跟上道题一样,唯一不同的点:
这道题可以不需要判断上题的第4点,因为 1*1 肯定会组成任意一个数,所以每个值在使用1的时候都会被初始化了。即,不存在无解的情况

以下是代码部分:

public class 完全平方数279 {

    public int numSquares(int n) {

        //组成i至少需要dp[i]个数
        int[] dp = new int[n+1];

        //0需要0个数
        dp[0] = 0;
        //其他数值初始化为最大值
        for (int i = 1; i < dp.length; i++) {
            dp[i] = Integer.MAX_VALUE;
        }

        for (int i = 1; i <= Math.sqrt(n); i++) {
            for (int j = i*i; j < n+1; j++) {

                //这里可以不用判断,因为 1*1 肯定会组成任意一个数,所以每个值在使用1的时候依旧被初始化了。
                if( 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、付费专栏及课程。

余额充值