lintcode582 - Word Break II - hard


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.
Example
Gieve s = lintcode,
dict = ["de", "ding", "co", "code", "lint"].
A solution is ["lint code", "lint co de"].

 

1.DFS,带记忆化搜索。
这题很容易TLE或MLE,尤其是当你试着扫描每段头尾不同的substring在不在字典里的时候会有很多重复功。减少时间复杂度的方法可以用记忆化搜索,比如1-5的分割我记下来了,以后6-10正好和1-5长一样,那我就不重新算,而是直接拿存过的分割结果了。实现这个功能的容器就是Map<String, List<String>>。
DFS函数头:private List<String> breakHelper(String s, Set<String> wordDict, Map<String, List<String>> memo)
目标:找出所有把s大卸八块的方式,拷贝一份放到memo里,再把这份方式返回。
流程:memo有了就直接拿了走人;遍历所有把s一分两半的方式,如果前半段字典里有,就DFS要一下所有后半段大卸八块的方式;把前半段和所有后半段的方式拼起来就是当前的结果了;存结果;返回结果。
细节:整个s就在字典里的情况要分出来处理,因为你没办法分s为s(0, length)和substring(length, length), 后面那样是编译错误的。

2.普通DFS
就是比较类似subset那些题目的做法,传index做,sb就像crt一样。但是会MLE哦,因为字典最长的可能也就5个字符,你一直拿30-1000的字符串去看在不在字典里,其实有很多无用功。前面那种做法其实也有这样做,但是它还是靠记忆化帮忙减少很多了,比如mmmmmmm…mmmmm走过一次流程发现没有分段方法,也会存个空集结果放到map里,下次再遇到一样的长字符串就不会再算了,直接返回空集上上级没办法粘出有效字符串。
细节:StringBuilder.delete(from, to)方法,里面填的参数和substring一样,头包括,尾包括,两者相减是长度。

 

 

1.DFS,带记忆化

public class Solution {
    /*
     * @param s: A string
     * @param wordDict: A set of words.
     * @return: All possible sentences.
     */
    public List<String> wordBreak(String s, Set<String> wordDict) {
        // write your code here
        List<String> result = new ArrayList<>();
        if (s == null || wordDict == null) {
            return result;
        }
        result = breakHelper(s, wordDict, new HashMap<String, List<String>>());
        return result;
    }
    
    private List<String> breakHelper(String s, Set<String> wordDict, Map<String, List<String>> memo) {
        
        if (memo.containsKey(s)) {
            return memo.get(s);
        }
        
        List<String> result = new ArrayList<>();
        for (int i = 1; i < s.length(); i++) {
            String substring = s.substring(0, i);
            if (!wordDict.contains(substring)) {
                continue;
            }
            List<String> suffixResult = breakHelper(s.substring(i), wordDict, memo);
            for (String item : suffixResult) {
                result.add(substring + " " + item);
            }
        }
        
        if (wordDict.contains(s)) {
            result.add(s);
        }
        
        memo.put(s, result);
        return result;
    }
}

 

2. 普通DFS,(正确但TLE)

public class Solution {
    /*
     * @param s: A string
     * @param wordDict: A set of words.
     * @return: All possible sentences.
     */
    public List<String> wordBreak(String s, Set<String> wordDict) {
        // write your code here
        List<String> result = new ArrayList<>();
        if (s == null || wordDict == null || (s.length() == 0 && !wordDict.contains(""))) {
            return result;
        }
        breakHelper(s, wordDict, 0, new StringBuilder(), result);
        return result;
    }
    
    private void breakHelper(String s, Set<String> wordDict, int index, StringBuilder sb, List<String> result) {
        
        if (index == s.length()) {
            result.add(sb.toString());
            return;
        }
        
        for (int i = index + 1; i <= s.length(); i++) {
            String substring = s.substring(index, i);
            if (!wordDict.contains(substring)) {
                continue;
            }
            if (index > 0) {
                sb.append(" ");
            }
            sb.append(substring);
            breakHelper(s, wordDict, i, sb, result);
            // 注意这个方法, 而且不可以sb.delete(index, i);,前面加了空格不一样了
            sb.delete(sb.length() - (i - index), sb.length());
            if (index > 0) {
                sb.delete(sb.length() - 1, sb.length());
            }
        }
    }
}

 

posted @ 2018-09-03 07:42  jasminemzy  阅读(281)  评论(0编辑  收藏  举报