[LeetCode] 140. Word Break II
Given a string s
and a dictionary of strings wordDict
, add spaces in s
to construct a sentence where each word is a valid dictionary word. Return all such possible sentences in any order.
Note that the same word in the dictionary may be reused multiple times in the segmentation.
Example 1:
Input: s = "catsanddog", wordDict = ["cat","cats","and","sand","dog"] Output: ["cats and dog","cat sand dog"]
Example 2:
Input: s = "pineapplepenapple", wordDict = ["apple","pen","applepen","pine","pineapple"] Output: ["pine apple pen apple","pineapple pen apple","pine applepen apple"] Explanation: Note that you are allowed to reuse a dictionary word.
Example 3:
Input: s = "catsandog", wordDict = ["cats","dog","sand","and","cat"] Output: []
Constraints:
1 <= s.length <= 20
1 <= wordDict.length <= 1000
1 <= wordDict[i].length <= 10
s
andwordDict[i]
consist of only lowercase English letters.- All the strings of
wordDict
are unique.
单词拆分 II。
给定一个字符串 s 和一个字符串字典 wordDict ,在字符串 s 中增加空格来构建一个句子,使得句子中所有的单词都在词典中。以任意顺序 返回所有这些可能的句子。
注意:词典中的同一个单词可能在分段中被重复使用多次。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/word-break-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题意跟139题很接近。139题问的是字符串 s 是否可以被 wordDict 中的单词们拼接起来(单词可以重复使用),本题请你返回的是拼接的具体结果是什么。
思路是DFS递归。回忆一下139题的做法,dp[i] 的含义是 s 中以 s[i] 作为结尾的子串是否存在于 wordDict。如果某一个 dp[i] 为 true,同时你还需要去看一下 s.substring(i, j),其中 i < j,是否存在于 wordDict,以确定整个 s 是否能满足题意。等于说是你看到 s 的左半边的 DP 值为 true 了,你去试着找找看右半边是否存在于 wordDict 以判断整个 s 是否能被拼接。
这道题可以试着用先去找后缀/右半边的方式递归去判断 s 是否能被拼接起来。如果一个后缀存在于 wordDict,那么我们递归处理前缀,并用 memo 存储结果避免重复计算。
时间O(n^n) - 极端情况是每个后缀都要逐个字母再递归下去看
空间O(n^n)
Java实现
1 class Solution { 2 public List<String> wordBreak(String s, List<String> wordDict) { 3 HashSet<String> set = new HashSet<>(wordDict); 4 return dfs(s, set, new HashMap<String, List<String>>()); 5 } 6 7 private List<String> dfs(String s, HashSet<String> set, HashMap<String, List<String>> map) { 8 if (s.length() == 0) { 9 return new ArrayList<>(); 10 } 11 if (map.containsKey(s)) { 12 return map.get(s); 13 } 14 List<String> res = new ArrayList<>(); 15 int n = s.length(); 16 for (int j = 0; j < s.length(); j++) { 17 // 如果后缀存在,则递归去看前缀 18 if (set.contains(s.substring(j, n))) { 19 // 空串的情况,直接加入 20 if (j == 0) { 21 // res.add(s.substring(j, s.length())); 22 res.add(s); 23 } else { 24 // 递归得到剩余字符串的所有组成可能,然后和当前字符串分别用空格连起来加到结果中 25 List<String> prefix = dfs(s.substring(0, j), set, map); 26 for (int k = 0; k < prefix.size(); k++) { 27 String p = prefix.get(k); 28 res.add(p + " " + s.substring(j, n)); 29 } 30 } 31 } 32 } 33 // 缓存结果 34 map.put(s, res); 35 return res; 36 } 37 }
相关题目