Day32 | 518零钱兑换 II&377组合总和 Ⅳ&70爬楼梯&322零钱兑换&279完全平方数&139单词拆分

128 阅读2分钟

零钱兑换 II LeetCode 518

题目链接:[LeetCode 518 - 中等]

思路

完全背包类问题:

①遍历顺序:先遍历物品后遍历背包

②初始化:dp[0]=1;

③与题意相关的问题:dp[j]+=dp[j-coins[i]];

动态规划:

class Solution {
    public int change(int amount, int[] coins) {
        int[] dp =new int[amount+1];
        dp[0]=1;
        for(int i=0;i<coins.length;i++){
            for(int j=coins[i];j<=amount;j++){
                dp[j]+=dp[j-coins[i]];
            }
        }
        return dp[amount];
    }
}

组合总和 Ⅳ LeetCode 377

题目链接:[LeetCode 377 - 中等]

思路

排列&组合类问题遍历的顺序不同

排列问题:先遍历物品后遍历背包

组合问题:先遍历背包后遍历物品

动态规划:

class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target+1];
        dp[0]=1;
        for(int j=0;j<=target;j++){
            for(int i=0;i<nums.length;i++){
                if(j >= nums[i]){
                    dp[j] += dp[j - nums[i]];
                }
            }
        }
        return dp[target];
    }
}

爬楼梯 LeetCode 70

题目链接:[LeetCode 70 - 简单]

思路

与#377基本一致

动态规划:

class Solution {
    public int climbStairs(int n) {
        int[] dp = new int[n+1];
        dp[0]=1;
        int[] b={1,2};
        for(int j=0;j<=n;j++){
            for(int i=0;i<b.length;i++){
                if(j>=b[i]){
                    dp[j]+=dp[j-b[i]];
                }
            }
        }
        return 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 332

题目链接:[LeetCode 332 - 中等]

思路

与#518思路相似,但是需要解决:

如果coins中的硬币不能够满足amount的金额要求:if(dp[j-coins[i]]!=max)

动态规划:

class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount+1];
        int max = Integer.MAX_VALUE;
        for(int i=1;i<=amount;i++){
            dp[i]=max;
        }
        for(int i=0;i<coins.length;i++){
            for(int j=coins[i];j<=amount;j++){
                if(dp[j-coins[i]]!=max){
                    dp[j]=Math.min(dp[j],dp[j-coins[i]]+1);
                }
            }
        }
        return dp[amount]==max?-1:dp[amount];
    }
}

完全平方数 LeetCode 279

题目链接:[LeetCode 279 - 中等]

思路

该题为排列问题(完全背包问题):

遍历顺序:先遍历物品后遍历背包

动态规划:

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n+1];
        int max = Integer.MAX_VALUE;
        for(int i=1;i<=n;i++){
            dp[i]=max;
        }
        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];
    }
}

单词拆分 LeetCode 139

题目链接:[LeetCode 139 - 中等]

思路

较难,多刷(看卡哥视频)

动态规划:

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        HashSet<String> set = new HashSet(wordDict);
        boolean[] valid = new boolean[s.length()+1];
        valid[0]=true;

        for(int i=0;i<=s.length();i++){
            for(int j=0;j<i&&!valid[i];j++){
                if(set.contains(s.substring(j,i))&&valid[j]){
                    valid[i]=true;
                }
            }
        }
        return valid[s.length()];
    }
}