Word Break
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = "leetcode"
,
dict = ["leet", "code"]
.
Return true because "leetcode"
can be segmented as "leet code"
.
解法1,递归,超时
有两种递归方式,一种是按s的子串递归,一种是按集合dict递归
第一种:
1 public boolean wordBreak(String s, Set<String> dict) { 2 if(dict.contains(s)){ 3 return true; 4 } 5 boolean flag = false; 6 for(int i=1;i<s.length();i++){ 7 if(dict.contains(s.substring(0,i))){ 8 flag = wordBreak(s.substring(i),dict); 9 } 10 } 11 return flag; 12 }
第二种:
1 public boolean wordBreak(String s, Set<String> dict) { 2 if(dict.contains(s)||s.equals("")){ 3 return true; 4 } 5 boolean flag = false; 6 for(String now:dict){ 7 for(int i = 0;i<s.length()-now.length();i++){ 8 if(s.substring(i, i+now.length()).equals(now)){ 9 flag = wordBreak(s.substring(0,i), dict)&&wordBreak(s.substring(i+now.length()), dict); 10 if(flag){ 11 return true; 12 } 13 } 14 } 15 } 16 return flag; 17 }
解法2:动态规划
设flag[]为boolean数组,flag[i]表示s.substring(0,i)是否满足wordbreak,因此有状态转移方程为:
flag[n] = ∑flag[i]&&s.substring(i,n) (i 取值为从1到n-1),有代码如下:
1 public boolean wordBreak(String s, Set<String> dict) { 2 boolean flag[] = new boolean[s.length()+1]; 3 flag[0] = true; 4 for(int i=1;i<=s.length();i++){ 5 for(int j=0;j<i;j++){ 6 flag[i] = flag[i] || (flag[j]&&dict.contains(s.substring(j, i))); 7 if(flag[i]){ 8 continue; 9 } 10 } 11 } 12 return flag[s.length()]; 13 }
递归的复杂度为O(2^n),动态规划的复杂度为O(n^2)
个人感觉,动态规划版本就是递归中第一种解法的非递归版,递归是自顶向下计算,动态规划是自底向上计算。
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"]
.
做法与上面相似,boolean数组变成list<Integer>的数组,记录当前位可以从前面哪些位得出,先自底向上生成数组,然后自顶向下构造字符串,直接贴代码:
1 private List<String> result = new ArrayList<String>(); 2 public List<String> wordBreak(String s, Set<String> dict) { 3 List<List<Integer>> flag = new ArrayList<List<Integer>>(); 4 List<Integer> temp = new ArrayList<Integer>(); 5 temp.add(0); 6 flag.add(temp); 7 for (int i = 1; i <= s.length(); i++) { 8 temp = new ArrayList<Integer>(); 9 for (int j = 0; j < i; j++) { 10 if (dict.contains(s.substring(j, i)) && flag.get(j).size() > 0) { 11 temp.add(j); 12 } 13 } 14 flag.add(temp); 15 } 16 genList(flag, s, "", flag.get(flag.size() - 1), flag.size() - 1); 17 return result; 18 } 19 20 private void genList(List<List<Integer>> flag, String source, String now, 21 List<Integer> list, int pos) { 22 // TODO Auto-generated method stub 23 if (pos == 0) { 24 result.add(now); 25 return; 26 } 27 for (Integer i : list) { 28 String temp = ""; 29 if (now.equals("")) { 30 temp = source.substring(i, pos); 31 32 } else { 33 temp = source.substring(i, pos) + " " + now; 34 } 35 genList(flag, source, temp, flag.get(i), i.intValue()); 36 } 37 }