139. 单词拆分
题目链接:139. 单词拆分
思路:
动规五部曲
1.确定dp数组以及下标的含义
dp[i]:dp[i] = true 表示字符串中前i个字符可以由字典里的字符拼成
2.确定递推公式
如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。
所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。
3.dp数组如何初始化
dp[0] = true。
4.确定遍历顺序
这题不是求排列组合,所以两层for顺序的前后顺序没有影响
代码:
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
HashSet<String> set = new HashSet<>();
for (String str : wordDict) {
set.add(str);
}
boolean[] valid = new boolean[s.length() + 1];
valid[0] = true;
for (int i = 1; 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()];
}
}
背包问题总结
问能否能装满背包(或者最多装多少): dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
问装满背包有几种方法: dp[j] += dp[j - nums[i]];
问背包装满最大价值: dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
问装满背包所有物品的最小个数: dp[j] = min(dp[j - coins[i]] + 1, dp[j]);
0-1背包
二维dp数组01背包先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。
一维dp数组01背包只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历(防止物品重复使用)。
完全背包
先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。
如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。