单词拆分两种做法(动规+记忆化搜索)

单词拆分

回溯法

普通的递归会超时,因为有大量的递归重复计算,所以我们可以使用记忆化搜索,创建一个memory数组,如果开始下标之后的字符串无法拆分,把该位置设为true,递归调用到的话直接返回,这种算法时间复杂度是O(n ^ 3),因为substring的时间复杂度是O(n),其实还可以再提速,把这里优化掉,我们可以使用字符串哈希算法,原理很简单,给你一个很长的字符串可能存不下和很长的数字可以存下,后者所占的空间会少很多,但主要还是为了方便判断一个字符串是否出现过,这是最基础的部分。
具体算法可以参考字符串哈希

class Solution {
    boolean[] memory;
    public boolean wordBreak(String s, List<String> wordDict) {
        //这道字符串拆分可以联想到回溯法暴力拆分,但是有可能超时,所以我们这里使用记忆化搜索
        Set<String> set = new HashSet<>(wordDict);
        this.memory = new boolean[s.length()];
        return backTracking(s,set,0);
    }
    public boolean backTracking(String s,Set<String>set,int startIndex) {
        if(s.length() == 0) return true;
        if(memory[startIndex]) return false;
        for(int i = 0;i < s.length();i++) {
            if(set.contains(s.substring(0,i + 1))) {
                if(backTracking(s.substring(i + 1),set,startIndex + i + 1)) {
                    return true;
                }
            }
        }
        memory[startIndex] = true;
        return false;
    }
}

动态规划

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        //dp数组定义,长度为i,是否可以拆分
        //递推公式:如果dp[j]是true且j到i的字串再字典里出现过,则dp[i]为true
        //初始化:dp[0] = true;这里没有实际意义,单纯为了状态转移方程
        //遍历顺序,物品和背包哪个在外面都可以,这里选用背包在外部
        boolean[] dp = new boolean[s.length() + 1];
        dp[0] = true;
        Set<String> set = new HashSet<>(wordDict);
        for(int i = 1;i <= s.length();i++) {
            for(int j = 0;j < i;j++) {
                if(dp[j] && set.contains(s.substring(j,i))) {
                    dp[i] = true;
                }
            }
        }
        return dp[s.length()];
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值