代码随想录算法训练营第四十五天| 卡码网57.爬楼梯、LeetCode322.零钱兑换、LeetCode279.完全平方数

卡码网 57 爬楼梯

题目链接:57. 爬楼梯(第八期模拟笔试) (kamacoder.com)

【解题思路】

  • 1.确定dp数组下标及其含义:

    • dp[j]表示爬到有j个台阶的楼顶,有dp[j]种方法

  • 2.确定递推公式

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

      • i代表一步走i个台阶

  • 3.dp数组初始化

    • 因为递推公式是累加的公式,所以dp[0]一定为1

    • 因为递推公式是累加公式,后面的数字都是由前面推导出来的,所以非0下标元素初始化为0

  • 4.确定遍历顺序

    • 这里是求的排列问题,因此:

      • 先遍历背包

        • 再遍历物品

    • 5.举例推导dp数组

      • 手动推导一下答案,然后将数组打印出来,看看每个状态是否按照我们的思路进行转移

【解题步骤】

  • 1.创建一个dp数组,初始化大小为n+1

  • 2.初始化dp[0]=1

  • 3.先遍历背包(n)

    • 再遍历物品(m)

      • 如果j-i大于等于0,说明还没走到顶,还能继续走:

        • 递推公式

  • 4.输出dp[n]

【代码部分】

import java.util.Scanner;
class climbStairs{
    public static void main(String [] args){
        Scanner sc = new Scanner(System.in);
        int m, n;
        while (sc.hasNextInt()) {
            n = sc.nextInt();
            m = sc.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 >= 0) dp[j] += dp[j - i];
                }
            }
            System.out.println(dp[n]);
        }
    }
}

LeetCode 322 零钱兑换

题目链接:

【解题思路】

  • 1.确定dp数组以及下标含义

    • dp[j]的定义是:装满容量为j的背包最少物品为dp[j]

    • 本题最终要求的是dp[amount]

  • 2.确定递推公式

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

      • 凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])

  • 3.确定dp数组如何初始化

    • dp[0]=0

    • dp数组的其他元素初始化为max

      • 因为要一直比较选最小的,因此不能初始化为0,只能初始化为int的最大值

  • 4.确定遍历顺序

    • 第一种,先遍历物品:

      • 再遍历背包:

        • 递推公式

    • 第二种,先遍历背包:

      • 再遍历物品:

        • 递推公式

    • Carl说先遍历物品是组合数,先遍历背包是排列数,对于这点,我的理解是:

      • 先遍历物品后遍历背包:

        • 1)外层固定物品1,进入内层循环

        • 2)背包容量不断增加

          • 物品1被重复添加进不同容量的背包中,直到背包容量遍历完毕

        • 3)背包容量遍历完毕后,执行下一次循环,开始添加物品2

          • 物品1已经被添加进每一个不同容量的背包里,因此物品2肯定会在物品1之后

      • 先遍历背包后遍历物品:

        • 1)外层循环固定背包容量

          • 在大小固定的背包里循环遍历添加物品,直到物品全遍历一次

        • 2)物品遍历结束,外层背包容量+1

          • 此时仍要执行内层循环,再次遍历一遍物品

          • 可能会出现如下情况:

            • 在上一轮遍历到物品3时,当前容量的背包已经没有办法塞入物品3,因此背包里此时有物品1和物品2

              • 在当前轮遍历的时候发现增加了容量的背包可以再添加一个物品1,就会有【物品1,物品2,物品1】这样的情况,所以很可能会有物品1出现在物品2之类的情况

    • 本题求组合还是求排列都不影响最终结果,因此先遍历物品还是背包都可以

  • 5.举例推导dp数组

    • 手动推导一下答案,然后将数组打印出来,看看每个状态是否是按照我们的思路进行转移的

【解题步骤】

  • 1.创建一个dp数组,大小为amount+1

  • 2.初始化dp数组为最大值,dp[0]=0

  • 3.遍历背包和物品:

    • 递推公式

      • 注意!!!

        • 在java中,最大值+1等于最小值!

        • 因此在dp[j-coins[i]]执行+1操作前,也就是在递推公式前,需要判断dp[j-coins[i]]是否为最大值,如果为最大值,就没有考虑的必要!!

  • 4返回

    • 如果dp[amount]==max,说明没有解,return-1

    • 如果dp[amount]!=max,返回dp[amount]

【代码部分】

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];
    }
}

LeetCode 279 完全平方数

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

【解题思路】

解题思路跟上一题几乎一样,只不过把coins[i]换成i*i

【解题步骤】

  • 1.创建一个dp数组,大小为n+1

  • 2.初始化dp数组为最大值,dp[0]=0

  • 3.遍历背包和物品:

    • 递推公式

      • 注意!!!

        • j需要始终大于i*i,不然没有意义

        • 但是不需要用if判断j-i*i下标是否等于max,因为在完全平方数这一题不会有“凑不成”的状况发生

  • 4返回

    • returndp[n]

【代码部分】

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];
    }
}

  • 14
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值