随想录Day46 | 139、 单词拆分 、背包总结 | 动态规划

78 阅读2分钟

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()];
    }
}

背包问题总结

背包问题总结 image

问能否能装满背包(或者最多装多少): 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循环遍历物品。