LeetCode 139. 单词拆分 DFS / DP java

给定一个非空字符串 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

解题思路
第一种方法:DFS 搜索
搜索遍历所有的子串,看子串是否在单词表中,如果该单词在单词表中并且剩余的子串也全部符合条件,那么整体的串就符合条件。
第二种方法: dp所有的位置 如果之前的符合条件,并且剩余子串也在单词表中,那么就记下该位置为true,最后返回最后位置的dp值。

代码

 public static boolean wordBreak(String s, List<String> wordDict) {   
        List<String> res = new ArrayList<>();    
        return  backTrace(s,res,0,s.length(),wordDict,new ArrayList<>());
           
       }
     
    private static boolean backTrace(String cs, List<String> res, int begin, int length, List<String> wordDict,List<Integer> checkedin) {
        if(begin == length){
            return true;
        }
        for(int i=begin+1;i<=length;i++){    
            if(checkedin.contains(i))continue;
            if(wordDict.contains(cs.substring(begin,i))){
                if (backTrace(cs, res, i, length,wordDict,checkedin))return true;
    //记录下从i开始判断的时候失败的情况,以免之后再重复计算                
            checkedin.add(i);
            }    
        }
        return false;
        
    }

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
 int len = s.length();
         int maxWordLength = 0;
         //这一步是说:对于检查一个字符串是否出现在给定的字符串列表里一般可以考虑哈希表来快速判断。(相对于list结构set的查询效率更高,但是是不是在创建这个set的时候也浪费了一些时间呢)
           Set<String> wordSet = new HashSet<>(wordDict.size());
            for (String word : wordDict) {
                wordSet.add(word);

                if (word.length() > maxWordLength) {
                    maxWordLength = word.length();
                }
            }
        boolean dp [] = new boolean[s.length()+1];
        dp[0] = true;
        for(int i =1;i<len+1;i++){
            //剪枝操作:如果i的位置大于了最大单词的长度,那么j的起始位置应该在 i减去最大长度的位置开始,因若不然s.substring(j,i)的长度是大于最大单词的 长度的,所以一定不可能匹配成功。
            for(int j =(i < maxWordLength ? 0:i-maxWordLength);j<i;j++){
                if(dp[j] && wordSet.contains(s.substring(j, i))){
                    dp[i] = true;
                    break;
                }
            }
        }
         return dp[len];
         
           
       }
     
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值