Word Break II
Given a string s and a dictionary of words dict, add spaces in s to
construct a sentence where each word is a valid dictionary
word.
Return all such possible sentences.
For example, given
s = "catsanddog",
dict = ["cat", "cats", "and", "sand", "dog"].
A solution is ["cats and dog", "cat sand dog"].
解答1 (dfs):
让我们来继续切切切吧!
本题与上一题Word Break思路类似,但是一个是DP,一个是DFS。
让我们来回顾一下DP与DFS的区别:
DP是Bottom-up 而DFS是TOP-DOWN.
在本题的DFS中,我们这样定义:
用刀在字符串中切一刀。左边是i个字符,右边是len-i个字符。
i: 1- len
如果:
左边是字典里的词,右边是可以wordbreak的,那么把左边的字符串加到右边算出来的List中,生成新的list返回。
1. Base case:
当输入字符串为空的时候,应该给出一个空解。这个很重要,否则这个递归是不能运行的。
2. 递归的时候,i应该从1开始递归,因为我们要把这个问题分解为2个部分,如果你左边给0,那就是死循环。
记忆:
为了加快DFS的速度,我们应该添加记忆,也就是说,算过的字符串不要再重复计算。举例子:
apple n feng
app len feng
如果存在以上2种划分,那么feng这个字符串会被反复计算,在这里至少计算了2次。我们使用一个Hashmap把对应字符串的解记下来,这样就能避免重复的计算。
否则这一道题目会超时。
1 // 我们用DFS来解决这个问题吧 2 public static List<String> wordBreak1(String s, Set<String> dict) { 3 HashMap<String, List<String>> map = new HashMap<String, List<String>>(); 4 if (s == null || s.length() == 0 || dict == null) { 5 return null; 6 } 7 8 return dfs(s, dict, map); 9 } 10 11 // 解法1:我们用DFS来解决这个问题吧 12 public static List<String> dfs(String s, Set<String> dict, HashMap<String, List<String>> map) { 13 if (map.containsKey(s)) { 14 return map.get(s); 15 } 16 17 List<String> list = new ArrayList<String>(); 18 int len = s.length(); 19 20 if (len == 0) { 21 list.add(""); 22 } else { 23 // i 表示左边字符串的长度 24 for (int i = 1; i <= len; i++) { 25 String sub = s.substring(0, i); 26 27 // 左边的子串可以为空,或是在字典内 28 if (!dict.contains(sub)) { 29 continue; 30 } 31 32 // 字符串划分为2边,计算右边的word break. 33 List<String> listRight = dfs(s.substring(i, len), dict, map); 34 35 // 右边不能break的时候,我们跳过. 36 if (listRight.size() == 0) { 37 continue; 38 } 39 40 // 把左字符串加到右字符串中,形成新的解. 41 for (String r: listRight) { 42 StringBuilder sb = new StringBuilder(); 43 sb.append(sub); 44 if (i != 0 && i != len) { 45 // 如果左边为空,或是右边为空,不需要贴空格 46 sb.append(" "); 47 } 48 sb.append(r); 49 list.add(sb.toString()); 50 } 51 } 52 } 53 54 map.put(s, list); 55 return list; 56 }