leetcode 140单词拆分Ⅱ

原想法:通过遍历找出每个位点可能出现的单词的列表,然后通过dfs遍历找出所有的组合,有点类似于之前刷pat时用的dijstra+dfs,代码如下

class Solution {
    List<String>[]startWordList;
    List<String>words=new ArrayList<>();
    List<String>result=new ArrayList<>();
    public void dfs(int cursor,int length){
        if(cursor>length){
            return;
        }else if(cursor==length){//这种情况即找到了结果
            String res="";
            for(int i=0;i<words.size();i++){
                if(i==0){
                    res=res+words.get(i);
                }else {
                    res=res+" "+words.get(i);
                }
            }
            result.add(res);
            return;
        }
        for(String word:startWordList[cursor]){
            words.add(word);
            dfs(cursor+word.length(),length);
            words.remove(words.size()-1);
        }
    }
    public List<String> wordBreak(String s, List<String> wordDict) {
        startWordList=new List[s.length()];
        for(int i=0;i<startWordList.length;i++){
            startWordList[i]=new ArrayList<>();
        }
        //先通过循环搜索出所有开始点可能出现的单词
        for(int i=0;i<s.length();i++){
            for(int j=i;j<=s.length();j++){
                String sub=s.substring(i,j);
                for(String word:wordDict){
                    if(word.equals(sub)){
                        startWordList[i].add(word);
                    }
                }
            }
        }
        dfs(0,s.length());
        return result;
    }
}

全是a的那个点运行超时了。

优化:记忆化搜索

标注不能达到终点的点,当每一次搜索结束后返回true or false,发现某个点不可达后将其哈希表中对应项标注,此后回溯后再次经过此点时则直接跳过。代码如下:

​```class Solution {
    List<String>[]startWordList;
    List<String>words=new ArrayList<>();
    List<String>result=new ArrayList<>();
    boolean[]cantAchieve;//记录某个点是否能达到终点
    public boolean dfs(int cursor,int length){
        if(cursor>length){
            return false;
        }else if(cursor==length){//这种情况即找到了结果
            String res="";
            for(int i=0;i<words.size();i++){
                if(i==0){
                    res=res+words.get(i);
                }else {
                    res=res+" "+words.get(i);
                }
            }
            result.add(res);
            return true;
        }
        if (cantAchieve[cursor]==false) {
            boolean find=false;
            for(String word:startWordList[cursor]){
                words.add(word);
                boolean ok=dfs(cursor+word.length(),length);
                words.remove(words.size()-1);
                if(ok==true){
                    find=ok;
                }
            }
            if(find==false){
                cantAchieve[cursor]=true;
            }
            return find;
        }else{
            return false;
        }
    }
    public List<String> wordBreak(String s, List<String> wordDict) {
        startWordList=new List[s.length()];
        cantAchieve=new boolean[s.length()];
        for(int i=0;i<startWordList.length;i++){
            startWordList[i]=new ArrayList<>();
        }
        //先通过循环搜索出所有开始点可能出现的单词
        for(int i=0;i<s.length();i++){
            for(int j=i;j<=s.length();j++){
                String sub=s.substring(i,j);
                for(String word:wordDict){
                    if(word.equals(sub)){
                        startWordList[i].add(word);
                    }
                }
            }
        }
        dfs(0,s.length());
        return result;
    }
}
原文地址:https://www.cnblogs.com/PanYuDi/p/14090750.html