-
139单词拆分
- 代码随想录 (programmercarl.com)
-
第一印象
- wordDict中元素相当于硬币,字符串s相当于背包,目的是装满背包。元素可以无限次重复使用,所以是完全背包问题。
-
讲解观后感
- dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。
- 递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。
- dp[0]一定要为true
- 本题的s一定是固定顺序的,我们要得到准确的顺序,本题一定是 先遍历背包,再遍历物品。
-
解题代码
-
func wordBreak(s string,wordDict []string) bool {
wordDictSet := make(map[string]bool)
for _, w := range wordDict {
wordDictSet[w] = true
}
dp := make([]bool, len(s)+1)
dp[0] = true
for i := 1; i <= len(s); i++ {
for j := 0; j < i; j++ {
if dp[j] && wordDictSet[s[j:i]] {
dp[i] = true
break
}
}
}
return dp[len(s)]
}
func wordBreak(s string, wordDict []string) bool {
dp := make([]int, len(s)+1)
dp[0] = 1
for i := 0; i <= len(s); i++ {
for j := 0; j < len(wordDict); j++ {
if i >= len(wordDict[j]) && wordDict[j] == s[i-len(wordDict[j]):i] {
dp[i] += dp[i-len(wordDict[j])]
}
}
}
return dp[len(s)] > 0
}
- 时间复杂度:O(n^3),因为substr返回子串的副本是O(n)的复杂度(这里的n是substring的长度)
- 空间复杂度:O(n)
-
多重背包
- 代码随想录 (programmercarl.com)
-
代码示意
- 两种思路,一种是将固定数量的某种物品,当成不同的物品,相同的属性,全部压入元素集。
-
package theory
import "log"
func multiplePack(weight, value, nums []int, bagWeight int) int {
for i := 0; i < len(nums); i++ {
for nums[i] > 1 {
weight = append(weight, weight[i])
value = append(value, value[i])
nums[i]--
}
}
log.Println(weight)
log.Println(value)
res := make([]int, bagWeight+1)
for i := 0; i < len(weight); i++ {
for j := bagWeight; j >= weight[i]; j-- {
res[j] = getMax(res[j], res[j-weight[i]]+value[i])
}
log.Println(res)
}
return res[bagWeight]
}
- 一种是在遍历过程中限制次数
- C++
-
void test_multi_pack() {
vector<int> weight = {1, 3, 4}
vector<int> value = {15, 20, 30}
vector<int> nums = {2, 3, 2}
int bagWeight = 10
vector<int> dp(bagWeight + 1, 0)
for(int i = 0
for(int j = bagWeight
// 以上为01背包,然后加一个遍历个数
for (int k = 1
dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i])
}
}
// 打印一下dp数组
for (int j = 0
cout << dp[j] << " "
}
cout << endl
}
cout << dp[bagWeight] << endl
}
int main() {
test_multi_pack()
}
-
背包总结
- 代码随想录 (programmercarl.com)