139. 单词拆分
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
HashSet<String> set = new HashSet<>(wordDict);
// dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。
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(set.contains(s.substring(j, i)) && dp[j])dp[i] = true;
}
}
return dp[s.length()];
}
}
0-1背包和完全背包总结
动规五步:
- 确定dp数组以及下标的含义
- 确定递推公式
- 确定dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
递推公式的确定
问能否能装满背包(或者最多装多少):dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);, 有的题目中 weight 和 value 是同一个数组,则对应为dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]),对应题目如下:
问装满背包有几种方法:dp[j] += dp[j - nums[i]];,对应题目如下:
问背包装满的最大价值:dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);,对应题目如下:
问装满背包所有物品的最小个数:dp[j] = Math.min(dp[j - weight[i]] + 1, dp[j]);,对应题目如下:
遍历顺序的确定
0-1背包
以二维数组遍历0-1背包问题,先遍历物品再遍历背包或者先遍历背包再遍历物品都是可以的,并且内层循环可以从前向后遍历。
以一维数组遍历0-1背包问题,只能先遍历物品再遍历背包,并且内层只能从后向前遍历,目的是确保每个物品只会被装入一次,不会被重复使用。
完全背包
纯完全背包问题:二维数组或一位数组遍历完全背包问题,先遍历物品或是先遍历背包都是可以的。并且内层循环从前往后遍历。
求组合数问题:外层for遍历物品,内层for遍历背包。物品在结果集合中的顺序无影响。
求排列数问题:外层for遍历背包,内层for遍历物品。物品在结果集合中的顺序有影响。
相关题目如下:
求最小数:两层for循环的先后顺序无所谓了。相关题目如下: 求最小数:动态规划:322. 零钱兑换;动态规划:279.完全平方数