代码随想录训练营第46天 | 139.单词拆分● 背包问题总结

139.单词拆分 

题目链接:https://leetcode.com/problems/word-break

解法:

单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。

拆分时可以重复使用字典中的单词,说明就是一个完全背包!

1.确定dp数组以及下标的含义

dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词

2.确定递推公式

如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

当然,内层循环也可以直接遍历字典。

3. dp数组如何初始化

除了 dp[0] = True,其他初始化为False。

4. 遍历顺序

排列问题,先背包后物品。由于是完全背包,背包和物品都是从前到后遍历。

边界条件:无

时间复杂度:O(nm)

空间复杂度:O(n)

class Solution(object):
    def wordBreak(self, s, wordDict):
        dp = [False] * (len(s)+1)
        dp[0] = True
        for i in range(1, len(s)+1):
            for word in wordDict:
                if i >= len(word):
                    dp[i] = dp[i] or (s[i-len(word):i] == word and dp[i-len(word)])
        return dp[-1]

背包问题总结

1.递推公式

问能否能装满背包(或者最多装多少):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])

2.遍历顺序
01 背包
二维dp数组01背包先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

一维dp数组01背包只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历。

完全背包。

纯完全背包的一维dp数组实现,先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

但是仅仅是纯完全背包的遍历顺序是这样的,题目稍有变化,两个for循环的先后顺序就不一样了。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

你可能感兴趣的:(数据结构和算法,算法,数据结构)