LeetCode - Word Break II

https://leetcode.com/problems/word-break-ii/

Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.

Return all such possible sentences.

For example, given
s = "catsanddog",
dict = ["cat", "cats", "and", "sand", "dog"].

A solution is ["cats and dog", "cat sand dog"].

这道题一开始一看该用递归做,但是递归是过不了的,因为超时。可以看到,在递归的话,每次都要从当前字符开始,一直到结束,检查substring是否在dict中,中间有许多重复的检查。因为,下面用的DP方法就是在一开始把所有的检查都完成,避免重复检查,并且适当剪枝。

public class Solution {
    public List<String> wordBreak(String s, Set<String> dict) {
        List<String> dp[] = new LinkedList[s.length()+1];
        dp[0] = new LinkedList<String>();
        for(int i=0; i<s.length(); i++){
            if(dp[i]==null) continue;   //剪枝,当前字符前面的字符串不能用dict中字符串中组合成,所以从当前字符开始的不用检查了
            for(String word:dict){
                int len = word.length();
                int end = i+len;
                if(end > s.length()) continue;
                if(s.substring(i, end).equals(word)){
                    if(dp[end]==null) dp[end] = new LinkedList<String>();
                    dp[end].add(word);
                }
            }
        }
        
        List<String> result = new ArrayList<String>();
        if(dp[s.length()]==null) return result;
        ArrayList<String> tmp = new ArrayList<String>();
        dfs(dp, result, tmp, s.length());
        return result;
    }
    
    public void dfs(List<String>[] dp, List<String> result, ArrayList<String> tmp, int end){
        if(end<=0){
            StringBuilder sb = new StringBuilder();
            for(int i=tmp.size()-1; i>=0; i--){
                sb.append(tmp.get(i));
                if(i!=0) sb.append(' ');
            }
            result.add(sb.toString());
            return;
        }
        for(String word: dp[end]){
            tmp.add(word);
            dfs(dp, result, tmp, end-word.length());
            tmp.remove(tmp.size()-1);
        }
    }
}

从这道题可以看到,避免重复计算和找到适当的剪枝方法非常重要!


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值