Word Break I II

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     }

posted @ 2014-06-10 18:35  秋风一片叶  阅读(224)  评论(0编辑  收藏  举报