LeetCode 139:Word Break

题意描述

给定一个非空字符串s和包含非空单词列表的字典wordDict,请确定s是否可以分段为一个或多个字典单词的以空格分隔的序列。

注:(1)字典中的同一单词可以在分割中多次重复使用。

(2)可以认为字典中没有重复的单词。

测试用例

Input: s = "leetcode", wordDict = ["leet", "code"]

Output: true

Explanation: Return true because "leetcode" can be segmented as "leet code".

Input: s = "applepenapple", wordDict = ["apple", "pen"]

Output: true

Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".

Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]

Output: false

解题思路

一、思路一

使用动态规划

  • 使用一个boolean类型的数组dp,dp[ i ] 表示 s[ 0 ... i ] 是否存在于字典中
  • 使用i逐个遍历字符串,使用j遍历【0-i】的子串。
  • 整个字符串分割为 ------- left substring ---- | substring (j, i + 1) | -------right substring ------
  • 如果我们知道当前子串substring 在字典中,而之前的子串也left substring在字典中,那么我们知道str.substring(0,i)是正确的。 J == 0,因为第一个子字符串之前没有任何内容(dp [j-1]不存在)
  • 如果我们知道str.substring(j,i + 1)在字典中,则只有在左边的子字符串也在字典中时,我们才能将其标记为true。 然后,对于右边的子字符串,它是str.substring(i +1,end)。如果您知道直到end的子字符串在字典中,您都只能将dp [end]标记为true。
    public boolean wordBreak(String s, List<String> wordDict) {
            if(s == null || s.length() == 0) return false;
            boolean[] dp = new boolean[s.length()];
            for(int i=0;i<s.length();i++){	//遍历s字符串
                for(int j = 0;j<=i;j++){	//遍历【0-i】的子串
                    if(j == 0 || dp[j-1]){	//dp【j-1】为true,说明【0,j-1】的子串都在字典中。
                        String sub = s.substring(j,i+1);//截取子串
                        if(wordDict.contains(sub)){	//判断知否在字典中
                            dp[i] = true;	//【0,i】都在字典中
                        }
                    }
                }
            }
            return dp[s.length()-1];
        }

二、思路二

使用DFS算法

  1. 使用一个Set集合保存在字典中找到不到匹配项的索引位置
  2. 遍历字符串,如果【0,i】的子串存在于字典中,则从i+1开始向后遍历,判断之后的子串是否存在于字典中。、
  3. 如果【i+1,end】都不存在于字典中,记录i+1的值,并回溯。
  4. 从i+2开始遍历
    private HashSet<Integer> set = new HashSet<>();
        public boolean wordBreak(String s, List<String> wordDict) {
            HashSet<Integer> set = new HashSet<>();//记录匹配不到的位置的索引
            return dfs(s,0,wordDict,set);
        }
        private boolean dfs(String s,int index,List wordDict,Set set){
            if(index == s.length()) return true;	
            if(set.contains(index)) return false;	//防止重复搜索
            for(int i=index+1;i<=s.length();i++){
                String sub = s.substring(index,i);
                //当【index,i)能够匹配到字典中的元素,从i开始继续匹配
                //如果【i,length)都匹配不到,则回溯,从上一个匹配到的子串继续向下匹配
                if(wordDict.contains(sub) && dfs(s,i,wordDict,set)){
                    return true;
                }
            }
            set.add(index);	//如果匹配不到,将匹配开始位置加入set
            return false;
        }

猜你喜欢

转载自www.cnblogs.com/le-le/p/12892000.html