leetcode之140单词拆分ⅡGolang
题目描述
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
- 分隔时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例 1:
输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
[
"cats and dog",
"cat sand dog"
]
示例 2:
输入:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
输出:
[
"pine apple pen apple",
"pineapple pen apple",
"pine applepen apple"
]
解释: 注意你可以重复使用字典中的单词。
示例 3:
输入:
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
输出:
[]
算法
-
首先使用动态规划的方式求出在字符串的什么地方拆分字符串为单词
-
从字符串的最后一个字符开始比较
假设
mid[i]表示从i开始到字符串最后能否拆分为单词,如果可以,mid[i]为true,否则为false -
那么当判断
mid[i-1]的时候,取数j,mid[i-1]为true的条件就是从i-1到i-1+j这之间所有字符组成的单词能在wordDict中找到,并且mid[i+j]的值同时为true,将所有满足这个条件的j找到,并且将i+j保存到二维数组midRes中 -
那么
midRes[i]的值是一个数组,里面的值就是从i开始,一直到字符串的最后,能够完美拆分为单词的前提下,从i,到下一次分割(也就是下一次插入空格的地方)
-
-
然后使用回溯法找出所有可能分割情况
- 使用递归
recursion(i int,tmp0 []byte) - 当递归到字符串的最后,递归结束
- 对
midRes[i]中的每一个值index,在index的地方插入空格 - 再次调用递归函数
recursion(index int,tmp []byte)
- 使用递归
代码
func wordBreak(s string, wordDict []string) []string {
wordsMap := make(map[string]struct{})
for _, word := range wordDict {
wordsMap[word] = struct{}{}
}
midIndexs := make([][]int, len(s)+1)
midRes := make([]bool, len(s)+1)
midIndexs[len(s)] = append(midIndexs[0], -1)
midRes[len(s)] = true
for i := len(s) - 1; i >= 0; i-- {
for j := 1; j+i <= len(s); j++ {
if _, ok := wordsMap[s[i:i+j]]; midRes[i+j] && ok {
midRes[i] = true
midIndexs[i] = append(midIndexs[i], i+j)
}
}
}
res := []string{}
if midRes[0] {
var recursion func(outer int, tmp []byte)
recursion = func(outer int, tmp []byte) {
if outer == len(s) {
res = append(res, string(tmp))
return
}
for _, index := range midIndexs[outer] {
midStr := make([]byte, len(tmp))
copy(midStr, tmp)
if len(tmp) > 0 {
midStr = append(midStr, ' ')
}
midStr = append(midStr, []byte(s)[outer:index]...)
recursion(index, midStr)
}
}
recursion(0, []byte{})
}
return res
}
浙公网安备 33010602011771号