Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences.

Note:

  • The same word in the dictionary may be reused multiple times in the segmentation.
  • You may assume the dictionary does not contain duplicate words.

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:
[]

这道题是之前那道Word Break 拆分词句的拓展,那道题只让我们判断给定的字符串能否被拆分成字典中的词,而这道题加大了难度,让我们求出所有可以拆分成的情况,就像题目中给的例子所示。之前的版本中字典wordDict的数据类型是HashSet,现在的不知为何改成了数组vector,而且博主看到第二个例子就笑了,PPAP么,哈哈~

根据老夫行走江湖多年的经验,像这种返回结果要列举所有情况的题,十有八九都是要用递归来做的。当我们一时半会没有啥思路的时候,先不要考虑代码如何实现,如果就给你一个s和wordDict,不看Output的内容,你会怎么找出结果。比如对于例子1,博主可能会先扫一遍wordDict数组,看有没有单词可以当s的开头,那么我们可以发现cat和cats都可以,比如我们先选了cat,那么此时s就变成了 "sanddog",我们再在数组里找单词,发现了sand可以,最后剩一个dog,也在数组中,于是一个结果就出来了。然后回到开头选cats的话,那么此时s就变成了 "anddog",我们再在数组里找单词,发现了and可以,最后剩一个dog,也在数组中,于是另一个结果也就出来了。那么这个查询的方法很适合用递归来实现,因为s改变后,查询的机制并不变,很适合调用递归函数。再者,我们要明确的是,如果不用记忆数组做减少重复计算的优化,那么递归方法跟brute force没什么区别,大概率无法通过OJ。所以我们要避免重复计算,如何避免呢,还是看上面的分析,如果当s变成 "sanddog"的时候,那么此时我们知道其可以拆分成sand和dog,当某个时候如果我们又遇到了这个 "sanddog"的时候,我们难道还需要再调用递归算一遍吗,当然不希望啦,所以我们要将这个中间结果保存起来,由于我们必须要同时保存s和其所有的拆分的字符串,那么可以使用一个HashMap,来建立二者之间的映射,那么在递归函数中,我们首先检测当前s是否已经有映射,有的话直接返回即可,如果s为空了,我们如何处理呢,题目中说了给定的s不会为空,但是我们递归函数处理时s是会变空的,这时候我们是直接返回空集吗,这里有个小trick,我们其实放一个空字符串返回,为啥要这么做呢?我们观察题目中的Output,发现单词之间是有空格,而最后一个单词后面没有空格,所以这个空字符串就起到了标记当前单词是最后一个,那么我们就不要再加空格了。接着往下看,我们遍历wordDict数组,如果某个单词是s字符串中的开头单词的话,我们对后面部分调用递归函数,将结果保存到rem中,然后遍历里面的所有字符串,和当前的单词拼接起来,这里就用到了我们前面说的trick。for循环结束后,记得返回结果res之前建立其和s之间的映射,方便下次使用,参见代码如下:

解法一:

class Solution {
public:
vector<string> wordBreak(string s, vector<string>& wordDict) {
unordered_map<string, vector<string>> m;
return helper(s, wordDict, m);
}
vector<string> helper(string s, vector<string>& wordDict, unordered_map<string, vector<string>>& m) {
if (m.count(s)) return m[s];
if (s.empty()) return {""};
vector<string> res;
for (string word : wordDict) {
if (s.substr(, word.size()) != word) continue;
vector<string> rem = helper(s.substr(word.size()), wordDict, m);
for (string str : rem) {
res.push_back(word + (str.empty() ? "" : " ") + str);
}
}
return m[s] = res;
}
};

我们也可以将将主函数本身当作递归函数,这样就不用单独的使用一个递归函数了,不过我们的HashMap必须是全局了,写在外部就好了,参见代码如下:

解法二:

class Solution {
public:
unordered_map<string, vector<string>> m;
vector<string> wordBreak(string s, vector<string>& wordDict) {
if (m.count(s)) return m[s];
if (s.empty()) return {""};
vector<string> res;
for (string word : wordDict) {
if (s.substr(, word.size()) != word) continue;
vector<string> rem = wordBreak(s.substr(word.size()), wordDict);
for (string str : rem) {
res.push_back(word + (str.empty() ? "" : " ") + str);
}
}
return m[s] = res;
}
};

类似题目:

Word Break

Concatenated Words

参考资料:

https://leetcode.com/problems/word-break-ii/description/

https://leetcode.com/problems/word-break-ii/solution/

https://leetcode.com/problems/word-break-ii/discuss/44167/My-concise-JAVA-solution-based-on-memorized-DFS

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Word Break II 拆分词句之二的更多相关文章

  1. [Leetcode] word break ii拆分词语

    Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...

  2. LeetCode: Word Break II 解题报告

    Word Break II Given a string s and a dictionary of words dict, add spaces in s to construct a senten ...

  3. LeetCode:Word Break II(DP)

    题目地址:请戳我 这一题在leetcode前面一道题word break 的基础上用数组保存前驱路径,然后在前驱路径上用DFS可以构造所有解.但是要注意的是动态规划中要去掉前一道题的一些约束条件(具体 ...

  4. LeetCode Word Break II

    原题链接在这里:https://leetcode.com/problems/word-break-ii/ 题目: Given a string s and a dictionary of words  ...

  5. [LeetCode] Word Break II 解题思路

    Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...

  6. [leetcode]Word Break II @ Python

    原题地址:https://oj.leetcode.com/problems/word-break-ii/ 题意: Given a string s and a dictionary of words  ...

  7. [LeetCode] Word Pattern II 词语模式之二

    Given a pattern and a string str, find if str follows the same pattern. Here follow means a full mat ...

  8. [LeetCode] Word Ladder II 词语阶梯之二

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

  9. [LeetCode] Word Search II 词语搜索之二

    Given a 2D board and a list of words from the dictionary, find all words in the board. Each word mus ...

随机推荐

  1. JavaScript : 零基础打造自己的类库

    写作不易,转载请注明出处,谢谢. 文章类别:Javascript基础(面向初学者) 前言 在之前的章节中,我们已经不依赖jQuery,单纯地用JavaScript封装了很多方法,这个时候,你一定会想, ...

  2. 利用Python进行数据分析(2) 尝试处理一份JSON数据并生成条形图

    一.JSON 数据准备 首先准备一份 JSON 数据,这份数据共有 3560 条内容,每条内容结构如下: 本示例主要是以 tz(timezone 时区) 这一字段的值,分析这份数据里时区的分布情况. ...

  3. MyCat源码分析系列之——前后端验证

    更多MyCat源码分析,请戳MyCat源码分析系列 MyCat前端验证 MyCat的前端验证指的是应用连接MyCat时进行的用户验证过程,如使用MySQL客户端时,$ mysql -uroot -pr ...

  4. html+ccs3太阳系行星运转动画

    做一个太阳系八大行星的运转动画,不包括行星的卫星,所有行星围绕太阳公转,行星采用纯色,暂时没有自转. 效果静态图: 动画中包括:太阳及各行星,运行轨道,行星公转动画. 先画好草图,设计好大小和位置,根 ...

  5. C#获取硬盘序列号的问题求助

    具体问题是这样的:我用下面这段获取硬盘型信息的代码做成的exe文件,在机子上测试的时候,出现直接双击运行和用管理员身份运行结果不一样的情况,这个问题该怎么解决? public static Strin ...

  6. C#开发微信门户及应用(12)-使用语音处理

    我们知道,微信最开始就是做语音聊天而使得其更加流行的,因此语音的识别处理自然也就成为微信交流的一个重要途径,微信的开发接口,也提供了对语音的消息请求处理.本文主要介绍如何利用语音的识别,对C#开发的微 ...

  7. Java判断字符串是否是数值

    判断一个字符串是否是数值,可以用正则表达式来判断.更简单的方法是把字符串转换成Float或者Double,然后捕捉NumberFormatException错误,如果有错误,就说明不是一个数值,如果没 ...

  8. SPI 2分频MOSI实现

    module spi_25M(input clk,input rst_n,output reg sdin,output reg sclk,output reg cs);reg [7:0]cnt;reg ...

  9. java的原子性操作有哪些

    Java中的原子操作包括:1)除long和double之外的基本类型的赋值操作2)所有引用reference的赋值操作3)java.concurrent.Atomic.* 包中所有类的一切操作coun ...

  10. Maven远程仓库的配置

    在很多情况下,默认的中央仓库无法满足项目的需求,可能项目需要的构件存在于另外一个远程仓库中,如JBoss Maven仓库.这时,可以在POM中配置该仓库,见代码如下: <!-- 远程仓库的配置 ...