代码随想录算法训练营第四十六天 |139. 单词拆分 背包问题总结

139. 单词拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s

**注意:**不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet""code" 拼接成。

题目当中可以将字符串列表当作物品,字符串s就是背包,最终需要求解单词能否组成字符串s,就是问物品能不能把背包装满

动规五部曲:

  1. 确定dp数组及下表含义

dp[i]表示组成字符串长度为i的话,dp[i]=true

  1. 确定递推公式

如果在[j,i]这个区间的子串中出现在字典里&&dp[j]=true,则dp[i]=true

  1. dp数组初始化

需要将dp[0]=true否则后续的结果将全部为false

  1. 确定遍历顺序

对于完全背包,如果求组合数就是外层for循环遍历物品,内层for遍历背包;如果求排列数就是外层for遍历背包,内层for循环遍历物品。这道题需要求得是排列,所以外层遍历背包,内层遍历物品。

  1. 举例推导dp[i]
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        HashSet<String> word=new HashSet<>(wordDict);
        boolean[] dp=new boolean[s.length()+1];
        dp[0]=true;

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

    }
}

多重背包忽略了!!!!

背包问题的递推公式:

  1. 问能否能装满背包(或者最多装多少):dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
  2. 问装满背包有几种方法:dp[j] += dp[j - nums[i]]
  3. 问背包装满最大价值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
  4. 问装满背包所有物品的最小个数:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

遍历顺序:

01背包——二维dp数组先遍历物品还是先遍历背包都是可以的,第二层是从小到大遍历;一维数组只能先遍历物品再遍历背包,第二层是从大到小

完全背包——如果求组合数就是外层for循环遍历物品,内层for循环遍历背包;如果求排列数就是外层for遍历背包,内层for循环遍历物品。

你可能感兴趣的:(算法,leetcode,动态规划)