Leetcode 之 Word Break1 和 Word Break2

来源:互联网 发布:金针软件客服 编辑:程序博客网 时间:2024/05/16 07:57

Word Beark1
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”.
和Word Break2
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”].

I 主要是判断字典中的单词能否组成句子,只要找到一组解就可以break,开始用递归,直接TLE,后来借鉴网上的方法用DP ,递推关系是f(n) = f(0,i) + f(i,j) + f(j,n),也就是遍历一遍整个句子,用两个下标来指示,跟字典比较来判断下标间能够构成一个单词。在遍历过程中,维护一个标记数组,记录在句子每一位时,它前面的部分是否能够构成部分句子。这样,我们只需要判断数组中句子的末尾的标记就可以。

public boolean wordBreak3(String s, Set<String> wordDict) {        boolean[] arrays = new boolean[s.length() + 1];        arrays[0] = true;        for(int i = 1;i <= s.length();i++){                     for(int j = 0;j < i;j++){                if(arrays[j] && wordDict.contains(s.subSequence(j, i))){                    arrays[i] = true;                    break;                }            }        }        return arrays[s.length()];    }

26 / 26 test cases passed.
Status: Accepted
Runtime: 252 ms

后来做II,与I的不同在于它不仅要判断能否找到,还要把所有可能的组合都列出来。开始想在找单词的同时生成组合,就用递归的方法:

把句子分成两部分,已经找到的剩下要找的子串。遍历整个字典,判断包含句子首位的单词是否在字典中有,如果没有的话可以直接返回了,如果有的话,在剩下要找的子串中中去掉这个单词,把这部分放到已经找到的部分,然后再递归。直到已经剩下要找的子串为空,说明全部找到,返回结果。

这里有几个需要注意的部分:
1、一定要与剩下要找的子串的首位进行比较。
2、在判断时,加入I时生成的标记数组进行判断进行剪枝,只有当这一位之前的部分能够构成句子,才需要进行下一步递归。
3、在递归前,先对字典中的单词进行了一遍筛选,如果单词在句子中没有,就直接在字典中删掉了,这样能够减少遍历字典的时间。

交上去,还是TLE,死在了字典里全是a,要找‘aaaaaaaa…ab’这个句子上,借鉴网上的做法,先用DP生成的标记数组来判断需不需要分割,如果字典不能组成句子的话就没必要进入递归了,加上这一步,AC了。

上一个java版本的代码:

    public List<String> result = new ArrayList<String>();    boolean[] arrays;    public List<String> wordBreak(String s, Set<String> wordDict) {        ArrayList<String> dic = new ArrayList<String>();        Iterator<String> iter = wordDict.iterator();        while(iter.hasNext()){            String word = iter.next();            if(s.indexOf(word) != -1){                dic.add(word);            }        }        arrays = new boolean[s.length() + 1];        arrays[0] = true;        for(int i = 1;i <= s.length();i++){                     for(int j = 0;j < i;j++){                if(arrays[j] && wordDict.contains(s.subSequence(j, i))){                    arrays[i] = true;                    break;                }            }        }        if(arrays[s.length()] == true)  find("","", s, dic);        return result;    }    /**     * 分割句子     * @param match 当前已匹配的子串(带空格)     * @param str 当前已匹配的子串(不带空格)     * @param string 剩余需要匹配的子串     * @param dic 字典     */    public void find(String match, String str, String string , ArrayList<String> dic){        if("".equals(string)){            result.add(match);            return;        }        for(String word:dic){            if(string.indexOf(word) == 0 && arrays[str.length()]){                String temp = match;                if("".equals(temp))                    temp = word;                 else                    temp += " "+word;                find(temp,str + word, string.substring(word.length()),dic);            }        }    }29 / 29 test cases passed.    Status: AcceptedRuntime: 296 ms
0 0
原创粉丝点击