力扣算法学习day29-3

力扣算法学习day29-3

377-组合总和 IV

题目

image-20220218222159922

image-20220218222213572

代码实现

class Solution {
    public int combinationSum4(int[] nums, int target) {
        // dp: 1ms      做过组合情况,这种情况就只是变一下遍历顺序而已,主要是原理理解要难点。
        // target很容易想到背包容量,且题目要求的是和为target的个数而不是组合,那么容易想到dp的背包问题
        // 由示例1可以知道,每个元素可以取多次,那么考虑完全背包解法,然后是求次数,考虑元素间的关系应该
        // 是有和的关系(先想背包问题的二维数组,在大脑很容易想到元素间应该是有符合条件迭代相加的关系。)
        // 然后,循序不同的序列被视为不同的组合,那么在遍历顺序考虑的时候,元素应该在内层遍历,使之结果为
        // 排列次数,而不是组合,具体的再具体看和修改。
        // 1.创建dp数组,dp[i] 表示目标和为i的元素组合(这里准确说叫排序)的个数。
        int[] dp = new int[target+1];

        // 2.迭代公式:dp[i] += dp[i-nums[j]],0 <= i <= target,j为nums数组元素
        // 3.初始化
        dp[0] = 1;// 为0,说明有本身那一种.即i-nums[j]=0

        // 4.确定遍历循序,上面已近分析,由于题目需要求的实际上是排列次数,简单的说就是元素组合顺序交换
        // 也算一种组合所以元素遍历需要在内层。
        for(int i = 1;i < dp.length;i++){
            for(int j = 0;j < nums.length;j++){
                if(i - nums[j] >= 0){
                    dp[i] += dp[i-nums[j]];
                }
            }
        }

        return dp[target];
    }
}

70-爬楼梯 --再回顾:完全背包解法

代码实现

class Solution {
    // 爬楼梯,背包版本
    // 注:背包思路换成能够爬1-m个台阶则更好换了,只需要换元素即可,已实验,两种方法解决1-m问题结果一样。
    public int climbStairs(int n) {
        // 题目分析,楼梯n阶,即n为背包容量,每次可以爬楼梯1,或2为元素,且为元素重量,元素可以重复取,为完全
        // 背包解法,然后通过示例2可以看出,组合结果如果顺序不同也会被视为一种组合方式,故次数是求排列结果。
        // 1.创建dp数组
        int[] dp = new int[n+1];

        // 2.确定迭代公式:dp[i] += dp[i-j],j为1,或2,即元素。
        // 3.初始化
        dp[0] = 1;

        // 4.确定遍历顺序
        for(int i = 1;i < dp.length;i++){
            for(int j = 1;j < 3;j++){
                if(i-j >= 0){
                    dp[i] += dp[i-j];
                }
            }
        }

        return dp[n];
    }




    // 以下为之前的,做过这道题。

    // 0ms
    // public int climbStairs(int n) {
    //     if(n < 3){
    //         return n;
    //     }
    //     // dp
    //     // 1.初始化dp数组
    //     int[] dp = new int[n];

    //     // 2.找递归公式:比如第三层,第一层跨2步能够到第三层,第二层跨1步能够到第三层
    //     // 用1,2标识是为了突出这两种情况,所以第一层的情况+第二层的情况=第三层的情况
    //     // 所以递归公式:dp[i] = dp[i-1] + dp[i-2];
    //     // 3.初始化dp数组
    //     dp[0] = 1;
    //     dp[1] = 2;

    //     // 4.找递归的顺序
    //     for(int i = 2;i < n;i++){
    //         dp[i] = dp[i-1] + dp[i-2];
    //     }

    //     // 5.略
    //     return dp[n-1];
    // }

    // 进阶思考:对于n阶楼梯,每次可以爬1-m个台阶问题的思考
    // int climbStairs(int n,int m) {
    //     // int m = 2;// 实验m=2本题是否成立,需要去掉输入的int m,结果通过 3ms
    //     // 创建dp数组
    //     int[] dp = new int[n];

    //     // 递归公式:i > m 由上面那道题很容易推出:dp[i] = dp[i-1] + dp[i-2] + ... + dp[i-m]
    //     //          i <= m,dp[i] = d[i-1] + d[i-2] + ... + d[0] + 1(本身)
    //     // 初始化
    //     dp[0] = 1;

    //     for (int i = 1; i < n; i++) {
    //         if(i < m){// 我这里0是第一层
    //             for(int j = 1;j <= i;j++){
    //                 dp[i] += dp[i-j];
    //             }
    //             dp[i]++;// 加上一步到位的情况
    //         } else{// i > m
    //             for(int j = 1;j <= m;j++){
    //                 dp[i] += dp[i-j];
    //             }
    //         }
    //     }

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

322-零钱兑换

题目

image-20220218235714816

image-20220218235727462

代码实现

class Solution {
    public int coinChange(int[] coins, int amount) {
        // dp 速度 10-11ms
        // 题目分析:看完题目,很明显需要用硬币凑成amount,所以考虑背包,硬币是元素,硬币面值是硬币重量,
        // amount是背包容量。每种硬币可以取多次,考虑完全背包,需要求总金额最少的硬币个数,那么硬币个数
        // 相当于是价值,而与常规相反,这里需要求满背包最小价值,所以迭代公式修改求最小应该就可以了。
        // 1.创建dp数组
        int[] dp = new int[amount+1];

        // 2.确定迭代公式:dp[i] = Math.min(dp[i],dp[i-coins[j]]+1),最小就求最小。
        // 3.初始化dp数组,因为是求最小,所以每个都初始化为最大即可。除了重量为0.
        for(int i = 1;i < dp.length;i++){
            dp[i] = Integer.MAX_VALUE;
        }

        // 4.确定遍历顺序,一样
        for(int i = 0;i < coins.length;i++){
            for(int j = coins[i];j < dp.length;j++){

                if(dp[j-coins[i]] != Integer.MAX_VALUE){
                    dp[j] = Math.min(dp[j],dp[j-coins[i]] + 1);
                }

                // System.out.print(dp[j]);
            }
            // System.out.println();
        }

        if(dp[amount] == Integer.MAX_VALUE){
            return -1;
        }

        return dp[amount];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人山人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值