139.单词拆分


给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。

你可以假设字典中没有重复的单词。

示例 1: 输入: s = "leetcode", wordDict = ["leet", "code"] 输出: true 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。

示例 2: 输入: s = "applepenapple", wordDict = ["apple", "pen"] 输出: true 解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。   注意你可以重复使用字典中的单词。

示例 3: 输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: false

 class Solution {
        HashSet set = new HashSet<>();
        public boolean wordBreak(String s, List wordDict) {

            for (String word : wordDict) {
                set.add(word);
            }
            List path = new ArrayList<>();
            return process(s.toCharArray(), 0, path);
        }

        private boolean process(char[] chs, int index, List path) {
            if (index == chs.length) {
                return set.contains(buildStr(path));
            }

            List pick = new ArrayList<>(path);
            pick.add(chs[index]);
            boolean p1 = process(chs, index + 1, pick);
            boolean p2 = false;
            if (set.contains(buildStr(pick))) {
                pick = new ArrayList<>();
                p2 = process(chs, index + 1, pick);
            }
            return p1 || p2;

        }

        private String buildStr(List path) {
            StringBuilder sb = new StringBuilder();
            for (char c : path) {
                sb.append(c);
            }
            return sb.toString();
        }
    }

  改成如下,方便做缓存优先

class Solution {
     HashSet set=new HashSet<>();
    public boolean wordBreak(String s, List wordDict) {
  
        for(String word:wordDict){
            set.add(word);
        }

        return process(s,0,0);
    }


    private boolean process(String s,int index,int j){
        if(index==s.length() ){
            String str=s.substring(j,index);
            return set.contains(s.substring(j,index));
        }
     
      boolean p1=  process(s,index+1,j);
      boolean p2=false;
      if(set.contains(s.substring(j,index+1))){
            j=index+1;
            p2=process(s,index+1,j);
        }
        return p1|| p2;
       
        
    }

}

递归的过程中有很多重复计算,可以使用数组保存一下递归过程中计算的结果。记忆化递归  

 class Solution {
        HashSet set = new HashSet<>();
        Map cacheMap = new HashMap();

        public boolean wordBreak(String s, List wordDict) {
            for (String word : wordDict) {
                set.add(word);
            }
            return process(s, 0, 0);
        }

        private boolean process(String s, int index, int j) {
            String key = j + "_" + index;
            if (cacheMap.containsKey(key)) {
                return cacheMap.get(key);
            }

            if (index == s.length()) {
                boolean ans = set.contains(s.substring(j, index));
                cacheMap.put(key, ans);
                return ans;
            }

            boolean p1 = process(s, index + 1, j);
            boolean p2 = false;
            if (set.contains(s.substring(j, index + 1))) {
                j = index + 1;
                p2 = process(s, index + 1, j);
            }
            boolean ans = p1 || p2;
            cacheMap.put(key, ans);
            return ans;
        }
    }