一、题目描述
给定一个非空字符串 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"]
输出:
[]
来源:力扣(LeetCode) 链接:单词拆分 II
二、算法思路
简单介绍一下, 这题做了两次(一次是刷题过程中遇到的, 一次是每日一题遇到的). 两次写的都是回溯, 然后超时了. 这题LeetCode有个很狗的数据, 所以要多做一步剪枝优化, 在这里记录一下
预处理一个数组f, f[i]表示从i这个位置开始到最后的字符串是否可以被划分为字典中的单词.
状态转移, j表示保留到的位置. 那么f[i] = f[j + 1] && 【s[i ~ j]在字典中存在】 最后就是dfs暴力搜索答案, 中途剪枝. 防止TLE.
三、AC代码
/**
* @param {string} s
* @param {string[]} wordDict
* @return {string[]}
*/
var wordBreak = function(s, wordDict) {
const ans = [], n = s.length;
const hash = {};
for(let word of wordDict) hash[word] = true;
const f = Array.from({length: n + 1}, () => false);
f[n] = true;
for(let i = n - 1; ~i; -- i)
for(let j = i; j < n; ++ j)
if(f[j + 1] && hash[s.substr(i, j - i + 1)])
f[i] = true;
dfs(0, "");
return ans;
function dfs(u, path) {
if(u == n) ans.push(path.substr(0, path.length - 1));
else {
for(let i = u; i < n; ++ i)
if(hash[s.substr(u, i - u + 1)] && f[i + 1])
dfs(i + 1, path + s.substr(u, i - u + 1) + " ");
}
}
};
本文正在参与「掘金 3 月闯关活动」,点击查看活动详情