2022-09-23 【我的刷题日记】322 279 零钱兑换和完全平方数

思路:零钱兑换和之前做的不同,这里的零钱兑换是一道完全背包问题,所有的零钱都可以被使用无数次,我们先定义大小为amount+1的dp数组,dp[j]表示总金额为j的最小组合的大小,dp[0]自然初始化为0.因为我们要求最小的大小,为了之后遍历的时候能顺利的更新最小值,dp数组未被初始化为特定数值的位置应当全都设置为最大的int值。
之后进行双重遍历,本题只求最小的组合大小,所以先遍历物品或者先遍历背包都是可以的,我这里习惯先遍历物品。在之前学习的基础上,很明显这里的递推公式应该为 dp[j]= Math.min(dp[j],dp[j - coins[i]]+1);整体代码如下

class Solution {
    public int coinChange(int[] coins, int amount) {
//        dp[j]定义为 总金额为j的最小组合的大小
        int[] dp = new int[amount + 1];
//        因为要选出最小的组合,所以先默认所有位置为最大 方便覆盖
        Arrays.fill(dp,Integer.MAX_VALUE);
//        dp[0]初始化为即组成0的组合大小为0即不存在
        dp[0] = 0;
//        先遍历物品 实际上先遍历背包也行
        for (int i = 0;i < coins.length;i++){
            for (int j = coins[i];j <= amount;j++){
//                当dp[j - coins[i]]有值的时候才有比较的意义
                if (dp[j - coins[i]] != Integer.MAX_VALUE){
                    dp[j]= Math.min(dp[j],dp[j - coins[i]]+1);
                }
            }
        }
//        当dp[amount]为最大值说明未经过修改 即达不到金额要求 返回-1 反之直接返回答案
        return dp[amount] == Integer.MAX_VALUE?(-1):dp[amount];

    }
}

思路:在上一道题的基础上做这道题很简单,只需要搞清楚什么是背包,什么是物品,按上一道题的思路直接进行求解即可,本题求完全平方和组成目标和的最小组合,很明显完全平方和是物品,目标和是背包大小。根据题意目标和1<=n<=10000 所以平方和的可选数值1<=i<=100,即物品是从1到100 物品价格是i*i 代入上一题的思路进行求解即可

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n+1];
        Arrays.fill(dp,Integer.MAX_VALUE);
        dp[0] = 0;
//        先遍历背包 题目提示i平方小于10000 所以这里直接写死小于等于100
        for (int i = 1; i <= 100; i++) {
            for (int j = i*i; j <= n ; j++) {
                if (dp[j - i*i]!=Integer.MAX_VALUE){
                    dp[j] = Math.min(dp[j],dp[j - i*i] + 1);
                }
            }
        }
        return dp[n];

    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容