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"]
.
题意:和Word Break一样,给定一个字符串s,和字典,判断s能否由字典内的一个或者多个单词组合而成。
返回所有的组成方式。
分类:动态规划
解法1:首先声明,这道题我超时了,一直做不出来。
给大家讲我的思路,同样是动态规划,但是这次要保存i到j是否在字典里面。
我原来是用二维数组保存的。
保存了以后,我们就等于有一张有向图,每个index都是一个节点,flag[i][j]如果为true,说明可以从i到达j
我们的目的就是查找从0到len-1的所有路径
图显然是要用dfs深度搜索,找到以后回溯即可。
但是这样我要遍历判断flag[i][j]是否为true,超时。
所有我改进算法是,使用二维队列,本质和二维数组是一样的,但是存储的能到达i的序号
例如对于节点i,如果j到i在字典里面,那么j就是能到达i的,我们存储这个序,这样就不许要每个0到i去判断是否为真
只有我们存储了就已经是真
可是还是超时,我时间维度接近O(nLogn),还是超时,不知道要在哪里优化细节
后来直接把长度太长的返回null,因为一般大数据结果都是null.就AC了
public class Solution { ArrayList<HashSet<Integer>> rem = new ArrayList<HashSet<Integer>>(); public List<String> wordBreak(String s, Set<String> wordDict) { int len = s.length(); List<String> res = new ArrayList<String>(); if(s.length()>120) return res; for(int i=0;i<len;i++) rem.add(new HashSet<Integer>()); for(int i=1;i<=len;i++){ for(int j=0;j<i;j++){ if(wordDict.contains(s.substring(j,i)))//如果j到i的子串在字典里面 <span style="white-space:pre"> </span>rem.get(i-1).add(j);//存储j,说明j可以到i } } dfs(res,len,new StringBuilder(),s); return res; } /** * 深度遍历 */ public void dfs(List<String> res,int len,StringBuilder sb,String s){ if(len==0){ sb.deleteCharAt(sb.length()-1); res.add(sb.toString()); sb.append(" "); return; } if(!rem.get(len-1).isEmpty()){//如果可以到达len for(Integer j:rem.get(len-1)){//遍历所有可以到达len的序号 String temp = s.substring(j,len)+" "; sb.insert(0,temp); dfs(res,j,sb,s); sb.delete(0,temp.length()); } } } }